protected override void TransitionForPresent() { if (MSAACount > 1) { var barriers = stackalloc D3D12_RESOURCE_BARRIER[2]; barriers[0] = D3D12_RESOURCE_BARRIER.InitTransition(MSAARenderTarget, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_RESOLVE_SOURCE); barriers[1] = D3D12_RESOURCE_BARRIER.InitTransition(RenderTarget, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RESOLVE_DEST); GraphicsCommandList->ResourceBarrier(2, barriers); GraphicsCommandList->ResolveSubresource(RenderTarget, 0, MSAARenderTarget, 0, BackBufferFormat); barriers[0] = D3D12_RESOURCE_BARRIER.InitTransition(MSAARenderTarget, D3D12_RESOURCE_STATE_RESOLVE_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); barriers[1] = D3D12_RESOURCE_BARRIER.InitTransition(RenderTarget, D3D12_RESOURCE_STATE_RESOLVE_DEST, D3D12_RESOURCE_STATE_PRESENT); GraphicsCommandList->ResourceBarrier(2, barriers); } else { var barriers = stackalloc D3D12_RESOURCE_BARRIER[2]; barriers[0] = D3D12_RESOURCE_BARRIER.InitTransition(MSAARenderTarget, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); barriers[1] = D3D12_RESOURCE_BARRIER.InitTransition(RenderTarget, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_COPY_DEST); GraphicsCommandList->ResourceBarrier(2, barriers); GraphicsCommandList->CopyResource(RenderTarget, MSAARenderTarget); barriers[0] = D3D12_RESOURCE_BARRIER.InitTransition(MSAARenderTarget, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); barriers[1] = D3D12_RESOURCE_BARRIER.InitTransition(RenderTarget, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PRESENT); GraphicsCommandList->ResourceBarrier(2, barriers); } }
private void PopulateCommandList() { // Command list allocators can only be reset when the associated // command lists have finished execution on the GPU; apps should use // fences to determine GPU execution progress. ThrowIfFailed(nameof(ID3D12CommandAllocator.Reset), _commandAllocator->Reset()); // However, when ExecuteCommandList() is called on a particular command // list, that command list can then be reset at any time and must be before // re-recording. ThrowIfFailed(nameof(ID3D12GraphicsCommandList.Reset), _commandList->Reset(_commandAllocator, _pipelineState)); // Set necessary state. _commandList->SetGraphicsRootSignature(_rootSignature); fixed(D3D12_VIEWPORT *viewport = &_viewport) { _commandList->RSSetViewports(1, viewport); } fixed(RECT *scissorRect = &_scissorRect) { _commandList->RSSetScissorRects(1, scissorRect); } // Indicate that the back buffer will be used as a render target. var barrier = D3D12_RESOURCE_BARRIER.InitTransition(_renderTargets[unchecked ((int)_frameIndex)], D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET); _commandList->ResourceBarrier(1, &barrier); var rtvHandle = _rtvHeap->GetCPUDescriptorHandleForHeapStart(); rtvHandle.ptr = (UIntPtr)((byte *)rtvHandle.ptr + (_frameIndex * _rtvDescriptorSize)); _commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, null); // Record commands. _isOnColorToggle = !_isOnColorToggle; var r = 0f; var g = _isOnColorToggle ? 25 / 255f : 54 / 255f; var b = _isOnColorToggle ? 70 / 255f : 52 / 255f; var clearColor = stackalloc float[4] { r, g, b, 1f }; _commandList->ClearRenderTargetView(rtvHandle, clearColor, NumRects: 0, null); _commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); fixed(D3D12_VERTEX_BUFFER_VIEW *vertexBufferView = &_vertexBufferView) { _commandList->IASetVertexBuffers(StartSlot: 0, 1, vertexBufferView); } _commandList->DrawInstanced(VertexCountPerInstance: 3, InstanceCount: 1, StartVertexLocation: 0, StartInstanceLocation: 0); // Indicate that the back buffer will now be used to present. barrier = D3D12_RESOURCE_BARRIER.InitTransition(_renderTargets[unchecked ((int)_frameIndex)], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT); _commandList->ResourceBarrier(1, &barrier); ThrowIfFailed(nameof(ID3D12GraphicsCommandList.Close), _commandList->Close()); }
public static D3D12_RESOURCE_BARRIER InitUAV(ID3D12Resource *pResource) { D3D12_RESOURCE_BARRIER result = default; result.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; result.Anonymous.UAV.pResource = pResource; return(result); }
/// <summary>Begins a new frame for rendering.</summary> /// <param name="backgroundColor">A color to which the background should be cleared.</param> public void BeginFrame(ColorRgba backgroundColor) { var frameIndex = SwapChain->GetCurrentBackBufferIndex(); _frameIndex = frameIndex; WaitForFence(Fences[frameIndex], FenceEvents[frameIndex], FenceValues[frameIndex]); var commandAllocator = CommandAllocators[frameIndex]; ThrowExternalExceptionIfFailed(nameof(ID3D12CommandAllocator.Reset), commandAllocator->Reset()); var graphicsCommandList = GraphicsCommandLists[frameIndex]; ThrowExternalExceptionIfFailed(nameof(ID3D12GraphicsCommandList.Reset), graphicsCommandList->Reset(commandAllocator, pInitialState: null)); var renderTargetDescriptorSize = Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); var renderTargetHandle = RenderTargetsHeap->GetCPUDescriptorHandleForHeapStart(); _ = renderTargetHandle.Offset((int)frameIndex, renderTargetDescriptorSize); graphicsCommandList->OMSetRenderTargets(1, &renderTargetHandle, RTsSingleHandleToDescriptorRange: TRUE, pDepthStencilDescriptor: null); var viewport = new D3D12_VIEWPORT { TopLeftX = 0.0f, TopLeftY = 0.0f, Width = _graphicsSurface.Width, Height = _graphicsSurface.Height, MinDepth = 0.0f, MaxDepth = 1.0f, }; graphicsCommandList->RSSetViewports(1, &viewport); var scissorRect = new RECT { left = 0, top = 0, right = (int)_graphicsSurface.Width, bottom = (int)_graphicsSurface.Height, }; graphicsCommandList->RSSetScissorRects(1, &scissorRect); var barrier = new D3D12_RESOURCE_BARRIER { Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE, Anonymous = new D3D12_RESOURCE_BARRIER._Anonymous_e__Union { Transition = new D3D12_RESOURCE_TRANSITION_BARRIER { pResource = RenderTargets[frameIndex], Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, StateBefore = D3D12_RESOURCE_STATE_PRESENT, StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET, }, }, }; graphicsCommandList->ResourceBarrier(1, &barrier); graphicsCommandList->ClearRenderTargetView(renderTargetHandle, (float *)&backgroundColor, NumRects: 0, pRects: null); }
public static D3D12_RESOURCE_BARRIER InitAliasing(ID3D12Resource *pResourceBefore, ID3D12Resource *pResourceAfter) { D3D12_RESOURCE_BARRIER result = default; result.Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING; result.Anonymous.Aliasing.pResourceBefore = pResourceBefore; result.Anonymous.Aliasing.pResourceAfter = pResourceAfter; return(result); }
public static D3D12_RESOURCE_BARRIER InitTransition(ID3D12Resource *pResource, D3D12_RESOURCE_STATES stateBefore, D3D12_RESOURCE_STATES stateAfter, uint subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, D3D12_RESOURCE_BARRIER_FLAGS flags = D3D12_RESOURCE_BARRIER_FLAG_NONE) { D3D12_RESOURCE_BARRIER result = default; result.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; result.Flags = flags; result.Anonymous.Transition.pResource = pResource; result.Anonymous.Transition.StateBefore = stateBefore; result.Anonymous.Transition.StateAfter = stateAfter; result.Anonymous.Transition.Subresource = subresource; return(result); }
/// <summary>Ends a render pass.</summary> /// <exception cref="InvalidOperationException">A render pass is not active.</exception> /// <exception cref="ObjectDisposedException">The context has been disposed.</exception> public void EndRenderPass() { var renderPass = Interlocked.Exchange(ref _renderPass, null); if (renderPass is null) { ThrowForInvalidState(nameof(RenderPass)); } var d3d12RtvResourceBarrier = D3D12_RESOURCE_BARRIER.InitTransition(renderPass.Swapchain.CurrentRenderTarget.D3D12RtvResource, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT); D3D12GraphicsCommandList->ResourceBarrier(1, &d3d12RtvResourceBarrier); }
private void PopulateCommandList() { // Command list allocators can only be reset when the associated // command lists have finished execution on the GPU; apps should use // fences to determine GPU execution progress. ThrowIfFailed(nameof(ID3D12CommandAllocator.Reset), _commandAllocator->Reset()); // However, when ExecuteCommandList() is called on a particular command // list, that command list can then be reset at any time and must be before // re-recording. ThrowIfFailed(nameof(ID3D12GraphicsCommandList.Reset), _commandList->Reset(_commandAllocator, _pipelineState)); // Set necessary state. _commandList->SetGraphicsRootSignature(_rootSignature); fixed(D3D12_VIEWPORT *viewport = &_viewport) { _commandList->RSSetViewports(1, viewport); } fixed(RECT *scissorRect = &_scissorRect) { _commandList->RSSetScissorRects(1, scissorRect); } // Indicate that the back buffer will be used as a render target. var barrier = D3D12_RESOURCE_BARRIER.InitTransition(_renderTargets[unchecked ((int)_frameIndex)], D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET); _commandList->ResourceBarrier(1, &barrier); var rtvHandle = _rtvHeap->GetCPUDescriptorHandleForHeapStart(); rtvHandle.ptr = (UIntPtr)((byte *)rtvHandle.ptr + (_frameIndex * _rtvDescriptorSize)); _commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, null); // Record commands. var clearColor = stackalloc float[4] { 0.0f, 0.2f, 0.4f, 1.0f }; _commandList->ClearRenderTargetView(rtvHandle, clearColor, NumRects: 0, null); // Execute the commands stored in the bundle. _commandList->ExecuteBundle(_bundle); // Indicate that the back buffer will now be used to present. barrier = D3D12_RESOURCE_BARRIER.InitTransition(_renderTargets[unchecked ((int)_frameIndex)], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT); _commandList->ResourceBarrier(1, &barrier); ThrowIfFailed(nameof(ID3D12GraphicsCommandList.Close), _commandList->Close()); }
public virtual void ResourceBarrier( uint NumBarriers, ref D3D12_RESOURCE_BARRIER pBarriers ) { var fp = GetFunctionPointer(26); if (m_ResourceBarrierFunc == null) { m_ResourceBarrierFunc = (ResourceBarrierFunc)Marshal.GetDelegateForFunctionPointer(fp, typeof(ResourceBarrierFunc)); } m_ResourceBarrierFunc(m_ptr, NumBarriers, ref pBarriers); }
/// <inheritdoc /> public override void BeginFrame(ColorRgba backgroundColor) { var graphicsFence = D3D12GraphicsFence; graphicsFence.Wait(); graphicsFence.Reset(); var commandAllocator = D3D12CommandAllocator; ThrowExternalExceptionIfFailed(nameof(ID3D12CommandAllocator.Reset), commandAllocator->Reset()); var graphicsCommandList = D3D12GraphicsCommandList; ThrowExternalExceptionIfFailed(nameof(ID3D12GraphicsCommandList.Reset), graphicsCommandList->Reset(commandAllocator, pInitialState: null)); var renderTargetResourceBarrier = D3D12_RESOURCE_BARRIER.InitTransition(D3D12RenderTargetResource, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET); graphicsCommandList->ResourceBarrier(1, &renderTargetResourceBarrier); var renderTargetView = D3D12RenderTargetView; graphicsCommandList->OMSetRenderTargets(1, &renderTargetView, RTsSingleHandleToDescriptorRange: TRUE, pDepthStencilDescriptor: null); var graphicsSurface = D3D12GraphicsDevice.GraphicsSurface; var graphicsSurfaceWidth = graphicsSurface.Width; var graphicsSurfaceHeight = graphicsSurface.Height; var viewport = new D3D12_VIEWPORT { Width = graphicsSurfaceWidth, Height = graphicsSurfaceHeight, MinDepth = D3D12_MIN_DEPTH, MaxDepth = D3D12_MAX_DEPTH, }; graphicsCommandList->RSSetViewports(1, &viewport); var scissorRect = new RECT { right = (int)graphicsSurfaceWidth, bottom = (int)graphicsSurfaceHeight, }; graphicsCommandList->RSSetScissorRects(1, &scissorRect); graphicsCommandList->ClearRenderTargetView(renderTargetView, (float *)&backgroundColor, NumRects: 0, pRects: null); graphicsCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); }
/// <inheritdoc /> public override void BeginDrawing(ColorRgba backgroundColor) { var graphicsCommandList = D3D12GraphicsCommandList; var renderTargetResourceBarrier = D3D12_RESOURCE_BARRIER.InitTransition(D3D12RenderTargetResource, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET); graphicsCommandList->ResourceBarrier(1, &renderTargetResourceBarrier); var renderTargetView = D3D12RenderTargetView; graphicsCommandList->OMSetRenderTargets(1, &renderTargetView, RTsSingleHandleToDescriptorRange: TRUE, pDepthStencilDescriptor: null); var graphicsSurface = D3D12GraphicsDevice.GraphicsSurface; var graphicsSurfaceWidth = graphicsSurface.Width; var graphicsSurfaceHeight = graphicsSurface.Height; var viewport = new D3D12_VIEWPORT { Width = graphicsSurfaceWidth, Height = graphicsSurfaceHeight, MinDepth = D3D12_MIN_DEPTH, MaxDepth = D3D12_MAX_DEPTH, }; graphicsCommandList->RSSetViewports(1, &viewport); var scissorRect = new RECT { right = (int)graphicsSurfaceWidth, bottom = (int)graphicsSurfaceHeight, }; graphicsCommandList->RSSetScissorRects(1, &scissorRect); graphicsCommandList->ClearRenderTargetView(renderTargetView, (float *)&backgroundColor, NumRects: 0, pRects: null); graphicsCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); var descriptorHeaps = stackalloc ID3D12DescriptorHeap *[1] { D3D12GraphicsDevice.D3D12ShaderResourceDescriptorHeap, }; graphicsCommandList->SetDescriptorHeaps(1, descriptorHeaps); }
/// <inheritdoc /> public override void EndFrame() { var graphicsCommandList = D3D12GraphicsCommandList; var renderTargetResourceBarrier = D3D12_RESOURCE_BARRIER.InitTransition(D3D12RenderTargetResource, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT); graphicsCommandList->ResourceBarrier(1, &renderTargetResourceBarrier); var commandQueue = D3D12GraphicsDevice.D3D12CommandQueue; ThrowExternalExceptionIfFailed(nameof(ID3D12GraphicsCommandList.Close), graphicsCommandList->Close()); commandQueue->ExecuteCommandLists(1, (ID3D12CommandList **)&graphicsCommandList); var executeGraphicsFence = WaitForExecuteCompletionGraphicsFence; ThrowExternalExceptionIfFailed(nameof(ID3D12CommandQueue.Signal), commandQueue->Signal(executeGraphicsFence.D3D12Fence, executeGraphicsFence.D3D12FenceSignalValue)); executeGraphicsFence.Wait(); executeGraphicsFence.Reset(); }
/// <summary> /// Mark a resource barrier on the command list /// </summary> /// <param name="resource">The resource to transition</param> /// <param name="transition">The transition</param> public void ResourceTransition(GpuResource resource, ResourceTransition transition) { // don't do unnecessary work if (resource.State == transition.NewState) { return; } var barrier = new D3D12_RESOURCE_BARRIER { Type = D3D12_RESOURCE_BARRIER_TYPE.D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, Flags = D3D12_RESOURCE_BARRIER_FLAGS.D3D12_RESOURCE_BARRIER_FLAG_NONE, Anonymous = new D3D12_RESOURCE_BARRIER._Anonymous_e__Union { Transition = CreateD3D12Transition(resource, transition) } }; resource.State = transition.NewState; _list.Get()->ResourceBarrier(1, &barrier); }
private void PopulateCommandList() { // Command list allocators can only be reset when the associated // command lists have finished execution on the GPU; apps should use // fences to determine GPU execution progress. ThrowIfFailed(nameof(ID3D12CommandAllocator.Reset), _commandAllocator->Reset()); // However, when ExecuteCommandList() is called on a particular command // list, that command list can then be reset at any time and must be before // re-recording. ThrowIfFailed(nameof(ID3D12GraphicsCommandList.Reset), _commandList->Reset(_commandAllocator, _pipelineState)); // Indicate that the back buffer will be used as a render target. var barrier = D3D12_RESOURCE_BARRIER.InitTransition(_renderTargets[unchecked ((int)_frameIndex)], D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET); _commandList->ResourceBarrier(1, &barrier); var rtvHandle = _rtvHeap->GetCPUDescriptorHandleForHeapStart(); rtvHandle.ptr = (UIntPtr)((byte *)rtvHandle.ptr + (_frameIndex * _rtvDescriptorSize)); // Record commands. var clearColor = stackalloc float[4]; { clearColor[0] = 0.0f; clearColor[1] = 0.2f; clearColor[2] = 0.4f; clearColor[3] = 1.0f; } _commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, null); // Indicate that the back buffer will now be used to present. barrier = D3D12_RESOURCE_BARRIER.InitTransition(_renderTargets[unchecked ((int)_frameIndex)], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT); _commandList->ResourceBarrier(1, &barrier); ThrowIfFailed(nameof(ID3D12GraphicsCommandList.Close), _commandList->Close()); }
/// <summary>Begins a render pass.</summary> /// <param name="renderPass">The render pass to begin.</param> /// <param name="renderTargetClearColor">The color to which the render target should be cleared.</param> /// <exception cref="ArgumentNullException"><paramref name="renderPass" /> is <c>null</c>.</exception> /// <exception cref="InvalidOperationException">A render pass is already active.</exception> /// <exception cref="ObjectDisposedException">The context has been disposed.</exception> public void BeginRenderPass(GraphicsRenderPass renderPass, ColorRgba renderTargetClearColor) { ThrowIfNull(renderPass); if (Interlocked.CompareExchange(ref _renderPass, renderPass, null) is not null) { ThrowForInvalidState(nameof(RenderPass)); } var d3d12GraphicsCommandList = D3D12GraphicsCommandList; var renderTarget = renderPass.Swapchain.CurrentRenderTarget; var d3d12RtvResourceBarrier = D3D12_RESOURCE_BARRIER.InitTransition(renderTarget.D3D12RtvResource, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET); d3d12GraphicsCommandList->ResourceBarrier(1, &d3d12RtvResourceBarrier); var d3d12RtvDescriptorHandle = renderTarget.D3D12RtvDescriptorHandle; d3d12GraphicsCommandList->OMSetRenderTargets(1, &d3d12RtvDescriptorHandle, RTsSingleHandleToDescriptorRange: TRUE, pDepthStencilDescriptor: null); d3d12GraphicsCommandList->ClearRenderTargetView(d3d12RtvDescriptorHandle, (float *)&renderTargetClearColor, NumRects: 0, pRects: null); d3d12GraphicsCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); }
/// <summary>Ends the frame currently be rendered.</summary> public void EndFrame() { var frameIndex = _frameIndex; var barrier = new D3D12_RESOURCE_BARRIER { Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE, Anonymous = new D3D12_RESOURCE_BARRIER._Anonymous_e__Union { Transition = new D3D12_RESOURCE_TRANSITION_BARRIER { pResource = RenderTargets[frameIndex], Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET, StateAfter = D3D12_RESOURCE_STATE_PRESENT, }, }, }; var graphicsCommandList = GraphicsCommandLists[frameIndex]; graphicsCommandList->ResourceBarrier(1, &barrier); ThrowExternalExceptionIfFailed(nameof(ID3D12GraphicsCommandList.Close), graphicsCommandList->Close()); CommandQueue->ExecuteCommandLists(1, (ID3D12CommandList **)&graphicsCommandList); }
public unsafe bool Render() { if (!_loadingComplete) { return(false); } ThrowIfFailed(_deviceResources.CommandAllocator->Reset()); ThrowIfFailed(_commandList.Ptr->Reset(_deviceResources.CommandAllocator, _pipelineState.Ptr)); { _commandList.Ptr->SetGraphicsRootSignature(_rootSignature.Ptr); const uint ppHeapsCount = 1; ID3D12DescriptorHeap **ppHeaps = stackalloc ID3D12DescriptorHeap *[(int)ppHeapsCount] { _cbvHeap.Ptr }; _commandList.Ptr->SetDescriptorHeaps(ppHeapsCount, ppHeaps); D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle; _cbvHeap.Ptr->GetGPUDescriptorHandleForHeapStart(&gpuHandle); gpuHandle.ptr += _deviceResources.CurrentFrameIndex * _cbvDescriptorSize; _commandList.Ptr->SetGraphicsRootDescriptorTable(0, gpuHandle); D3D12_VIEWPORT viewport = _deviceResources.ScreenViewport; _commandList.Ptr->RSSetViewports(1, &viewport); D3D12_RECT rect = _scissorRect; _commandList.Ptr->RSSetScissorRects(1, &rect); D3D12_RESOURCE_BARRIER renderTargetResourceBarrier = CD3DX12_RESOURCE_BARRIER.Transition( _deviceResources.RenderTarget, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET ); _commandList.Ptr->ResourceBarrier(1, &renderTargetResourceBarrier); D3D12_CPU_DESCRIPTOR_HANDLE renderTargetView = _deviceResources.RenderTargetView; D3D12_CPU_DESCRIPTOR_HANDLE depthStencilView = _deviceResources.DepthStencilView; _commandList.Ptr->ClearRenderTargetView(renderTargetView, CornflowerBlue, 0, null); _commandList.Ptr->ClearDepthStencilView(depthStencilView, D3D12_CLEAR_FLAG_DEPTH, 1, 0, 0, null); _commandList.Ptr->OMSetRenderTargets(1, &renderTargetView, FALSE, &depthStencilView); _commandList.Ptr->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); D3D12_VERTEX_BUFFER_VIEW vertexBufferView = _vertexBufferView; D3D12_INDEX_BUFFER_VIEW indexBufferView = _indexBufferView; _commandList.Ptr->IASetVertexBuffers(0, 1, &vertexBufferView); _commandList.Ptr->IASetIndexBuffer(&indexBufferView); _commandList.Ptr->DrawIndexedInstanced(36, 1, 0, 0, 0); D3D12_RESOURCE_BARRIER presentResourceBarrier = CD3DX12_RESOURCE_BARRIER.Transition( _deviceResources.RenderTarget, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT); _commandList.Ptr->ResourceBarrier(1, &presentResourceBarrier); } ThrowIfFailed(_commandList.Ptr->Close()); const uint ppCommandListsCount = 1; ID3D12CommandList **ppCommandLists = stackalloc ID3D12CommandList *[(int)ppCommandListsCount] { (ID3D12CommandList *)_commandList.Ptr }; _deviceResources.CommandQueue->ExecuteCommandLists(ppCommandListsCount, ppCommandLists); return(true); }
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); } }
protected virtual void TransitionForPresent() { var barrier = D3D12_RESOURCE_BARRIER.InitTransition(RenderTarget, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT); GraphicsCommandList->ResourceBarrier(1, &barrier); }
/// <inheritdoc/> public override unsafe void OnUpdate(TimeSpan time) { if (this.isResizePending) { ApplyResize(); this.isResizePending = false; } // Generate the new frame GraphicsDevice.Default.ForEach(this.texture !, this.shaderFactory(time)); using ComPtr <ID3D12Resource> d3D12Resource = default; // Get the underlying ID3D12Resource pointer for the texture _ = InteropServices.TryGetID3D12Resource(this.texture !, Windows.__uuidof <ID3D12Resource>(), (void **)d3D12Resource.GetAddressOf()); // Get the target back buffer to update ID3D12Resource *d3D12ResourceBackBuffer = this.currentBufferIndex switch { 0 => this.d3D12Resource0.Get(), 1 => this.d3D12Resource1.Get(), _ => null }; this.currentBufferIndex ^= 1; // Reset the command list and command allocator this.d3D12CommandAllocator.Get()->Reset(); this.d3D12GraphicsCommandList.Get()->Reset(this.d3D12CommandAllocator.Get(), null); D3D12_RESOURCE_BARRIER *d3D12ResourceBarriers = stackalloc D3D12_RESOURCE_BARRIER[] { D3D12_RESOURCE_BARRIER.InitTransition( d3D12Resource.Get(), D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COPY_SOURCE), D3D12_RESOURCE_BARRIER.InitTransition( d3D12ResourceBackBuffer, D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COPY_DEST) }; // Transition the resources to COPY_DEST and COPY_SOURCE respectively d3D12GraphicsCommandList.Get()->ResourceBarrier(2, d3D12ResourceBarriers); // Copy the generated frame to the target back buffer d3D12GraphicsCommandList.Get()->CopyResource(d3D12ResourceBackBuffer, d3D12Resource.Get()); d3D12ResourceBarriers[0] = D3D12_RESOURCE_BARRIER.InitTransition( d3D12Resource.Get(), D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_UNORDERED_ACCESS); d3D12ResourceBarriers[1] = D3D12_RESOURCE_BARRIER.InitTransition( d3D12ResourceBackBuffer, D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COMMON); // Transition the resources back to COMMON and UNORDERED_ACCESS respectively d3D12GraphicsCommandList.Get()->ResourceBarrier(2, d3D12ResourceBarriers); d3D12GraphicsCommandList.Get()->Close(); // Execute the command list to perform the copy this.d3D12CommandQueue.Get()->ExecuteCommandLists(1, (ID3D12CommandList **)d3D12GraphicsCommandList.GetAddressOf()); this.d3D12CommandQueue.Get()->Signal(this.d3D12Fence.Get(), this.nextD3D12FenceValue); // Present the new frame this.dxgiSwapChain1.Get()->Present(0, 0); if (this.nextD3D12FenceValue > this.d3D12Fence.Get()->GetCompletedValue()) { this.d3D12Fence.Get()->SetEventOnCompletion(this.nextD3D12FenceValue, default); } this.nextD3D12FenceValue++; } }
private void PopulateCommandList() { // Command list allocators can only be reset when the associated // command lists have finished execution on the GPU; apps should use // fences to determine GPU execution progress. ThrowIfFailed(nameof(ID3D12CommandAllocator.Reset), _commandAllocator->Reset()); // However, when ExecuteCommandList() is called on a particular command // list, that command list can then be reset at any time and must be before // re-recording. ThrowIfFailed(nameof(ID3D12GraphicsCommandList.Reset), _commandList->Reset(_commandAllocator, _pipelineState)); // Set necessary state. _commandList->SetGraphicsRootSignature(_rootSignature); fixed(D3D12_VIEWPORT *viewport = &_viewport) { _commandList->RSSetViewports(1, viewport); } fixed(RECT *scissorRect = &_scissorRect) { _commandList->RSSetScissorRects(1, scissorRect); } var rtvHandle = _rtvHeap->GetCPUDescriptorHandleForHeapStart(); _commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, null); // Record commands. var clearColor = stackalloc float[4] { 0.0f, 0.2f, 0.4f, 1.0f }; _commandList->ClearRenderTargetView(rtvHandle, clearColor, NumRects: 0, null); _commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); fixed(D3D12_VERTEX_BUFFER_VIEW *vertexBufferView = &_vertexBufferView) { _commandList->IASetVertexBuffers(StartSlot: 0, 1, vertexBufferView); } _commandList->DrawInstanced(VertexCountPerInstance: 3, InstanceCount: 1, StartVertexLocation: 0, StartInstanceLocation: 0); // If MSAA is enabled, we need to resolve the resource from the multi-sampled render target to the single-sampled back buffer if (_msaaDesc.Count > 1) { var barriers = stackalloc D3D12_RESOURCE_BARRIER[2]; barriers[0] = D3D12_RESOURCE_BARRIER.InitTransition(_multiSampledRenderTarget, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_RESOLVE_SOURCE); barriers[1] = D3D12_RESOURCE_BARRIER.InitTransition(_renderTargets[_frameIndex], D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RESOLVE_DEST); _commandList->ResourceBarrier(2, barriers); _commandList->ResolveSubresource(_renderTargets[_frameIndex], 0, _multiSampledRenderTarget, 0, DXGI_FORMAT_B8G8R8A8_UNORM); barriers[0] = D3D12_RESOURCE_BARRIER.InitTransition(_multiSampledRenderTarget, D3D12_RESOURCE_STATE_RESOLVE_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); barriers[1] = D3D12_RESOURCE_BARRIER.InitTransition(_renderTargets[unchecked ((int)_frameIndex)], D3D12_RESOURCE_STATE_RESOLVE_DEST, D3D12_RESOURCE_STATE_PRESENT); _commandList->ResourceBarrier(2, barriers); } else { var barriers = stackalloc D3D12_RESOURCE_BARRIER[2]; barriers[0] = D3D12_RESOURCE_BARRIER.InitTransition(_multiSampledRenderTarget, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); barriers[1] = D3D12_RESOURCE_BARRIER.InitTransition(_renderTargets[_frameIndex], D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_COPY_DEST); _commandList->ResourceBarrier(2, barriers); _commandList->CopyResource(_renderTargets[_frameIndex], _multiSampledRenderTarget); barriers[0] = D3D12_RESOURCE_BARRIER.InitTransition(_multiSampledRenderTarget, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); barriers[1] = D3D12_RESOURCE_BARRIER.InitTransition(_renderTargets[unchecked ((int)_frameIndex)], D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PRESENT); _commandList->ResourceBarrier(2, barriers); } // Indicate that the back buffer will now be used to present. ThrowIfFailed(nameof(ID3D12GraphicsCommandList.Close), _commandList->Close()); }
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 } }
/// <inheritdoc cref="Copy(GraphicsBuffer, GraphicsBuffer)" /> public void Copy(D3D12GraphicsBuffer destination, D3D12GraphicsBuffer source) { ThrowIfNull(destination, nameof(destination)); ThrowIfNull(source, nameof(source)); var graphicsCommandList = D3D12GraphicsCommandList; var destinationCpuAccess = destination.GraphicsHeap.CpuAccess; var sourceCpuAccess = source.GraphicsHeap.CpuAccess; var d3d12DestinationResource = destination.D3D12Resource; var d3d12SourceResource = source.D3D12Resource; var d3d12DestinationResourceState = destination.D3D12ResourceState; var d3d12SourceResourceState = source.D3D12ResourceState; BeginCopy(); graphicsCommandList->CopyResource(d3d12DestinationResource, d3d12SourceResource); EndCopy(); void BeginCopy() { var resourceBarriers = stackalloc D3D12_RESOURCE_BARRIER[2]; var numResourceBarriers = 0u; if (destinationCpuAccess == GraphicsHeapCpuAccess.None) { resourceBarriers[numResourceBarriers] = D3D12_RESOURCE_BARRIER.InitTransition( d3d12DestinationResource, stateBefore: d3d12DestinationResourceState, stateAfter: D3D12_RESOURCE_STATE_COPY_DEST ); numResourceBarriers++; } if (sourceCpuAccess == GraphicsHeapCpuAccess.None) { resourceBarriers[numResourceBarriers] = D3D12_RESOURCE_BARRIER.InitTransition( d3d12SourceResource, stateBefore: d3d12SourceResourceState, stateAfter: D3D12_RESOURCE_STATE_COPY_SOURCE ); numResourceBarriers++; } if (numResourceBarriers != 0) { graphicsCommandList->ResourceBarrier(numResourceBarriers, resourceBarriers); } } void EndCopy() { var resourceBarriers = stackalloc D3D12_RESOURCE_BARRIER[2]; var numResourceBarriers = 0u; if (sourceCpuAccess == GraphicsHeapCpuAccess.None) { resourceBarriers[numResourceBarriers] = D3D12_RESOURCE_BARRIER.InitTransition( d3d12SourceResource, stateBefore: D3D12_RESOURCE_STATE_COPY_SOURCE, stateAfter: d3d12SourceResourceState ); numResourceBarriers++; } if (destinationCpuAccess == GraphicsHeapCpuAccess.None) { resourceBarriers[numResourceBarriers] = D3D12_RESOURCE_BARRIER.InitTransition( d3d12DestinationResource, stateBefore: D3D12_RESOURCE_STATE_COPY_DEST, stateAfter: d3d12DestinationResourceState ); numResourceBarriers++; } if (numResourceBarriers != 0) { graphicsCommandList->ResourceBarrier(numResourceBarriers, resourceBarriers); } } }
/// <inheritdoc cref="Copy(GraphicsTexture, GraphicsBuffer)" /> public void Copy(D3D12GraphicsTexture destination, D3D12GraphicsBuffer source) { ThrowIfNull(destination, nameof(destination)); ThrowIfNull(source, nameof(source)); var graphicsDevice = D3D12GraphicsDevice.D3D12Device; var graphicsCommandList = D3D12GraphicsCommandList; var destinationCpuAccess = destination.GraphicsHeap.CpuAccess; var sourceCpuAccess = source.GraphicsHeap.CpuAccess; var d3d12DestinationResource = destination.D3D12Resource; var d3d12SourceResource = source.D3D12Resource; var d3d12DestinationResourceState = destination.D3D12ResourceState; var d3d12SourceResourceState = source.D3D12ResourceState; BeginCopy(); D3D12_PLACED_SUBRESOURCE_FOOTPRINT sourceFootprint; var destinationDesc = d3d12DestinationResource->GetDesc(); graphicsDevice->GetCopyableFootprints(&destinationDesc, FirstSubresource: 0, NumSubresources: 1, BaseOffset: 0, &sourceFootprint, pNumRows: null, pRowSizeInBytes: null, pTotalBytes: null); var d3d12DestinationTextureCopyLocation = new D3D12_TEXTURE_COPY_LOCATION(d3d12DestinationResource, Sub: 0); var d3d12SourceTextureCopyLocation = new D3D12_TEXTURE_COPY_LOCATION(d3d12SourceResource, in sourceFootprint); graphicsCommandList->CopyTextureRegion(&d3d12DestinationTextureCopyLocation, DstX: 0, DstY: 0, DstZ: 0, &d3d12SourceTextureCopyLocation, pSrcBox: null); EndCopy(); void BeginCopy() { var resourceBarriers = stackalloc D3D12_RESOURCE_BARRIER[2]; var numResourceBarriers = 0u; if (destinationCpuAccess == GraphicsHeapCpuAccess.None) { resourceBarriers[numResourceBarriers] = D3D12_RESOURCE_BARRIER.InitTransition( d3d12DestinationResource, stateBefore: d3d12DestinationResourceState, stateAfter: D3D12_RESOURCE_STATE_COPY_DEST ); numResourceBarriers++; } if (sourceCpuAccess == GraphicsHeapCpuAccess.None) { resourceBarriers[numResourceBarriers] = D3D12_RESOURCE_BARRIER.InitTransition( d3d12SourceResource, stateBefore: d3d12SourceResourceState, stateAfter: D3D12_RESOURCE_STATE_COPY_SOURCE ); numResourceBarriers++; } if (numResourceBarriers != 0) { graphicsCommandList->ResourceBarrier(numResourceBarriers, resourceBarriers); } } void EndCopy() { var resourceBarriers = stackalloc D3D12_RESOURCE_BARRIER[2]; var numResourceBarriers = 0u; if (sourceCpuAccess == GraphicsHeapCpuAccess.None) { resourceBarriers[numResourceBarriers] = D3D12_RESOURCE_BARRIER.InitTransition( d3d12SourceResource, stateBefore: D3D12_RESOURCE_STATE_COPY_SOURCE, stateAfter: d3d12SourceResourceState ); numResourceBarriers++; } if (destinationCpuAccess == GraphicsHeapCpuAccess.None) { resourceBarriers[numResourceBarriers] = D3D12_RESOURCE_BARRIER.InitTransition( d3d12DestinationResource, stateBefore: D3D12_RESOURCE_STATE_COPY_DEST, stateAfter: d3d12DestinationResourceState ); numResourceBarriers++; } if (numResourceBarriers != 0) { graphicsCommandList->ResourceBarrier(numResourceBarriers, resourceBarriers); } } }
/// <inheritdoc /> public override void EndDrawing() { var renderTargetResourceBarrier = D3D12_RESOURCE_BARRIER.InitTransition(D3D12RenderTargetResource, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT); D3D12GraphicsCommandList->ResourceBarrier(1, &renderTargetResourceBarrier); }
// 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(); } } }