Пример #1
0
        public void CreateAccelerationStructures()
        {
            acs = new AccelerationStructures();

            long mTlasSize = 0;

            ID3D12Resource[] mpVertexBuffer = new ID3D12Resource[2];
            mpVertexBuffer[0] = acs.CreateTriangleVB(mpDevice);
            mpVertexBuffer[1] = acs.CreatePlaneVB(mpDevice);

            // The first bottom-level buffer is for the plane and the triangle
            int[] vertexCount = new int[] { 3, 6 }; // Triangle has 3 vertices, plane has 6
            AccelerationStructureBuffers[] bottomLevelBuffers = new AccelerationStructureBuffers[2];
            bottomLevelBuffers[0] = acs.CreateBottomLevelAS(mpDevice, mpCmdList, mpVertexBuffer, vertexCount, 2);
            mpBottomLevelAS       = new ID3D12Resource[2];
            mpBottomLevelAS[0]    = bottomLevelBuffers[0].pResult;

            // The second bottom-level buffer is for the triangle only
            bottomLevelBuffers[1] = acs.CreateBottomLevelAS(mpDevice, mpCmdList, mpVertexBuffer, vertexCount, 1);
            mpBottomLevelAS[1]    = bottomLevelBuffers[1].pResult;

            // Create the TLAS
            AccelerationStructureBuffers topLevelBuffers = acs.CreateTopLevelAS(mpDevice, mpCmdList, mpBottomLevelAS, ref mTlasSize);

            // The tutorial doesn't have any resource lifetime management, so we flush and sync here. This is not required by the DXR spec - you can submit the list whenever you like as long as you take care of the resources lifetime.
            mFenceValue = context.SubmitCommandList(mpCmdList, mpCmdQueue, mpFence, mFenceValue);
            mpFence.SetEventOnCompletion(mFenceValue, mFenceEvent);
            mFenceEvent.WaitOne();
            int bufferIndex = mpSwapChain.GetCurrentBackBufferIndex();

            mpCmdList.Reset(mFrameObjects[0].pCmdAllocator, null);

            // Store the AS buffers. The rest of the buffers will be released once we exit the function
            mpTopLevelAS = topLevelBuffers.pResult;
        }
Пример #2
0
 public void Wait(ulong fenceValue)
 {
     if (_fence.CompletedValue < fenceValue)
     {
         _fence.SetEventOnCompletion(fenceValue, _fenceEvent);
         _fenceEvent.WaitOne();
     }
 }
Пример #3
0
 public void Wait(long fenceValue)
 {
     if (fence.CompletedValue < (ulong)fenceValue)
     {
         fence.SetEventOnCompletion((ulong)fenceValue, fenceEvent);
         fenceEvent.WaitOne();
     }
 }
Пример #4
0
        public void CreateAccelerationStructures()
        {
            acs = new AccelerationStructures();

            AccelerationStructureBuffers bottomLevelBuffers = acs.CreateBottomLevelAS(mpDevice, mpCmdList);
            AccelerationStructureBuffers topLevelBuffers    = acs.CreateTopLevelAS(mpDevice, mpCmdList, bottomLevelBuffers.pResult, ref mTlasSize);

            // The tutorial doesn't have any resource lifetime management, so we flush and sync here. This is not required by the DXR spec - you can submit the list whenever you like as long as you take care of the resources lifetime.
            mFenceValue = context.SubmitCommandList(mpCmdList, mpCmdQueue, mpFence, mFenceValue);
            mpFence.SetEventOnCompletion(mFenceValue, mFenceEvent);
            mFenceEvent.WaitOne();
            int bufferIndex = mpSwapChain.GetCurrentBackBufferIndex();

            mpCmdList.Reset(mFrameObjects[0].pCmdAllocator, null);

            // Store the AS buffers. The rest of the buffers will be released once we exit the function
            mpTopLevelAS    = topLevelBuffers.pResult;
            mpBottomLevelAS = bottomLevelBuffers.pResult;
        }
Пример #5
0
        private void EndFrame(int rtvIndex)
        {
            context.ResourceBarrier(mpCmdList, mFrameObjects[rtvIndex].swapChainBuffer, ResourceStates.RenderTarget, ResourceStates.Present);
            mFenceValue = context.SubmitCommandList(mpCmdList, mpCmdQueue, mpFence, mFenceValue);
            mpSwapChain.Present(0, 0);

            // Prepare the command list for the next frame
            int bufferIndex = mpSwapChain.GetCurrentBackBufferIndex();

            // Make sure we have the new back-buffer is ready
            if (mFenceValue > context.kDefaultSwapChainBuffers)
            {
                mpFence.SetEventOnCompletion(mFenceValue - context.kDefaultSwapChainBuffers + 1, mFenceEvent);
                this.mFenceEvent.WaitOne();
            }

            mFrameObjects[bufferIndex].pCmdAllocator.Reset();
            mpCmdList.Reset(mFrameObjects[bufferIndex].pCmdAllocator, null);
        }
Пример #6
0
        internal void WaitForFence(ID3D12Fence fence, long fenceValue)
        {
            if (IsFenceComplete(fence, fenceValue))
            {
                return;
            }

            using ManualResetEvent fenceEvent = new ManualResetEvent(false);
            fence.SetEventOnCompletion(fenceValue, fenceEvent);

            fenceEvent.WaitOne();
        }
Пример #7
0
        internal Task WaitForFenceAsync(ID3D12Fence fence, long fenceValue)
        {
            if (IsFenceComplete(fence, fenceValue))
            {
                return(Task.CompletedTask);
            }

            ManualResetEvent fenceEvent = new ManualResetEvent(false);

            fence.SetEventOnCompletion(fenceValue, fenceEvent);

            return(WaitHandleAsyncFactory.FromWaitHandle(fenceEvent));
        }
Пример #8
0
        internal Task WaitForFenceAsync(ID3D12Fence fence, long fenceValue)
        {
            if (IsFenceComplete(fence, fenceValue))
            {
                return(Task.CompletedTask);
            }

            lock (fenceLock)
            {
                fence.SetEventOnCompletion(fenceValue, fenceEvent);

                return(WaitHandleAsyncFactory.FromWaitHandle(fenceEvent));
            }
        }
Пример #9
0
        internal void WaitForFence(ID3D12Fence fence, long fenceValue)
        {
            if (IsFenceComplete(fence, fenceValue))
            {
                return;
            }

            lock (fenceLock)
            {
                fence.SetEventOnCompletion(fenceValue, fenceEvent);

                fenceEvent.WaitOne();
            }
        }
Пример #10
0
        private void EndFrame(int rtvIndex)
        {
            InsertTransitionResourceBarrier(frameObjects[rtvIndex].swapChainBuffer, ResourceStates.CopyDestination, ResourceStates.Present);
            SubmitCommandList();

            swapChain.Present(0, PresentFlags.None);

            var bufferIndex = swapChain.GetCurrentBackBufferIndex();

            if (fenceValue > DefaultSwapChainBuffers)
            {
                fence.SetEventOnCompletion(fenceValue - DefaultSwapChainBuffers + 1, fenceEvent);
                fenceEvent.WaitOne();
            }

            frameObjects[bufferIndex].cmdAllocator.Reset();
            commandList.Reset(frameObjects[bufferIndex].cmdAllocator, null);
        }
Пример #11
0
        /// <summary>
        /// Executes a <see cref="CommandList"/> and waits for the GPU to finish processing it
        /// </summary>
        /// <param name="commandList">The input <see cref="CommandList"/> to execute</param>
        internal void ExecuteCommandList(CommandList commandList)
        {
            ID3D12Fence fence = commandList.CommandListType switch
            {
                CommandListType.Direct => NativeDirectFence,
                CommandListType.Compute => NativeComputeFence,
                CommandListType.Copy => NativeCopyFence,
                _ => throw new NotSupportedException("This command list type is not supported.")
            };

            long fenceValue = GetFenceValueForCommandList(commandList);

            if (fenceValue <= fence.CompletedValue)
            {
                return;
            }

            fence.SetEventOnCompletion(fenceValue, default(IntPtr));
        }
Пример #12
0
        private void WaitForPreviousFrame()
        {
            // WAITING FOR THE FRAME TO COMPLETE BEFORE CONTINUING IS NOT BEST PRACTICE.
            // This is code implemented as such for simplicity. The D3D12HelloFrameBuffering
            // sample illustrates how to use fences for efficient resource usage and to
            // maximize GPU utilization.

            // Signal and increment the fence value.
            var fenceValueToSignal = _fenceValue;

            _d3d12CommandQueue.Signal(_d3d12Fence, fenceValueToSignal);
            _fenceValue++;

            // Wait until the previous frame is finished.
            if (_d3d12Fence.CompletedValue < fenceValueToSignal)
            {
                _d3d12Fence.SetEventOnCompletion(fenceValueToSignal, _fenceEvent);
                _fenceEvent.WaitOne();
            }

            _frameIndex = SwapChain3.GetCurrentBackBufferIndex();
        }
Пример #13
0
        /// <summary>
        /// Executes a <see cref="CommandList"/> and waits for the GPU to finish processing it
        /// </summary>
        /// <param name="commandList">The input <see cref="CommandList"/> to execute</param>
        internal void ExecuteCommandList(CommandList commandList)
        {
            ID3D12Fence fence = commandList.CommandListType switch
            {
                CommandListType.Direct => NativeDirectFence,
                CommandListType.Compute => NativeComputeFence,
                CommandListType.Copy => NativeCopyFence,
                _ => throw new NotSupportedException("This command list type is not supported.")
            };

            long fenceValue = GetFenceValueForCommandList(commandList);

            if (fenceValue <= fence.CompletedValue)
            {
                return;
            }

            lock (fence)
            {
                fence.SetEventOnCompletion(fenceValue, AutoResetEvent.SafeWaitHandle.DangerousGetHandle());
                AutoResetEvent.WaitOne();
            }
        }
Пример #14
0
    public static void Main()
    {
        using ID3D12Device device = D3D12CreateDevice <ID3D12Device>(null, FeatureLevel.Level_12_1);

        using IDStorageFactory factory = DStorageGetFactory <IDStorageFactory>();

        string fileToLoad = "Test.txt";
        Result result     = factory.OpenFile(fileToLoad, out IDStorageFile? file);

        if (result.Failure)
        {
            Console.WriteLine($"The file '{fileToLoad}' could not be opened. HRESULT={result}");
            //ShowHelpText();
            return;
        }

        ByHandleFileInformation info = file !.FileInformation;
        uint fileSize = info.FileSizeLow;

        // Create a DirectStorage queue which will be used to load data into a buffer on the GPU.
        QueueDesc queueDesc = new QueueDesc
        {
            Capacity   = MaxQueueCapacity,
            Priority   = Priority.Normal,
            SourceType = RequestSourceType.File,
            Device     = device
        };

        using IDStorageQueue queue = factory.CreateQueue(queueDesc);

        // Create the ID3D12Resource buffer which will be populated with the file's contents
        HeapProperties      bufferHeapProps = new HeapProperties(HeapType.Default);
        ResourceDescription bufferDesc      = ResourceDescription.Buffer(fileSize);

        using ID3D12Resource bufferResource = device.CreateCommittedResource(
                  bufferHeapProps,
                  HeapFlags.None,
                  bufferDesc,
                  ResourceStates.Common
                  );

        // Enqueue a request to read the file contents into a destination D3D12 buffer resource.
        // Note: The example request below is performing a single read of the entire file contents.
        Request request = new Request();

        request.Options.SourceType          = RequestSourceType.File;
        request.Options.DestinationType     = RequestDestinationType.Buffer;
        request.Source.File.Source          = file;
        request.Source.File.Offset          = 0;
        request.Source.File.Size            = fileSize;
        request.UncompressedSize            = fileSize;
        request.Destination.Buffer.Resource = bufferResource;
        request.Destination.Buffer.Offset   = 0;
        request.Destination.Buffer.Size     = request.Source.File.Size;
        queue.EnqueueRequest(request);

        // Configure a fence to be signaled when the request is completed
        using ID3D12Fence fence         = device.CreateFence();
        using AutoResetEvent fenceEvent = new AutoResetEvent(false);

        ulong fenceValue = 1;

        fence.SetEventOnCompletion(fenceValue, fenceEvent).CheckError();
        queue.EnqueueSignal(fence, fenceValue);

        // Tell DirectStorage to start executing all queued items.
        queue.Submit();

        // Wait for the submitted work to complete
        Console.WriteLine("Waiting for the DirectStorage request to complete...");
        fenceEvent.WaitOne();

        // Check the status array for errors.
        // If an error was detected the first failure record
        // can be retrieved to get more details.
        ErrorRecord errorRecord = queue.RetrieveErrorRecord();

        if (errorRecord.FirstFailure.HResult.Failure)
        {
            //
            // errorRecord.FailureCount - The number of failed requests in the queue since the last
            //                            RetrieveErrorRecord call.
            // errorRecord.FirstFailure - Detailed record about the first failed command in the enqueue order.
            //
            Console.WriteLine($"The DirectStorage request failed! HRESULT={errorRecord.FirstFailure.HResult}");
        }
        else
        {
            Console.WriteLine("The DirectStorage request completed successfully!");
        }
    }