public ID3D12Resource CreateBuffer(ID3D12Device5 pDevice, uint size, ResourceFlags flags, ResourceStates initState, HeapProperties heapProps) { ResourceDescription bufDesc = new ResourceDescription(); bufDesc.Alignment = 0; bufDesc.DepthOrArraySize = 1; bufDesc.Dimension = ResourceDimension.Buffer; bufDesc.Flags = flags; bufDesc.Format = Format.Unknown; bufDesc.Height = 1; bufDesc.Layout = TextureLayout.RowMajor; bufDesc.MipLevels = 1; bufDesc.SampleDescription = new SampleDescription(1, 0); bufDesc.Width = size; ID3D12Resource pBuffer = pDevice.CreateCommittedResource(heapProps, HeapFlags.None, bufDesc, initState, null); return(pBuffer); }
public ID3D12Resource CreatePlaneVB(ID3D12Device5 pDevice) { Vector3[] vertices = new Vector3[] { new Vector3(-100, -1, -2), new Vector3(100, -1, 100), new Vector3(-100, -1, 100), new Vector3(-100, -1, -2), new Vector3(100, -1, -2), new Vector3(100, -1, 100), }; // For simplicity, we create the vertex buffer on the upload heap, but that's not required ID3D12Resource pBuffer = CreateBuffer(pDevice, (uint)(Unsafe.SizeOf <Vector3>() * vertices.Length), ResourceFlags.None, ResourceStates.GenericRead, kUploadHeapProps); IntPtr pData = pBuffer.Map(0, null); Helpers.MemCpy(pData, vertices, (uint)(Unsafe.SizeOf <Vector3>() * vertices.Length)); pBuffer.Unmap(0, null); return(pBuffer); }
private void InitDXR(IntPtr winHandle, int winWidth, int winHeight) { mHwnd = winHandle; this.mSwapChainRect = new Rect(0, 0, winWidth, winHeight); // Initialize the debug layer for debug builds #if DEBUG if (D3D12.D3D12GetDebugInterface <ID3D12Debug>(out var pDx12Debug).Success) { pDx12Debug.EnableDebugLayer(); } #endif // Create the DXGI factory IDXGIFactory4 pDXGIFactory; DXGI.CreateDXGIFactory1 <IDXGIFactory4>(out pDXGIFactory); mpDevice = this.context.CreateDevice(pDXGIFactory); mpCmdQueue = this.context.CreateCommandQueue(mpDevice); mpSwapChain = this.context.CreateDXGISwapChain(pDXGIFactory, mHwnd, winWidth, winHeight, Format.R8G8B8A8_UNorm, mpCmdQueue); // Create a RTV descriptor heap mRtvHeap.Heap = this.context.CreateDescriptorHeap(mpDevice, kRtvHeapSize, DescriptorHeapType.RenderTargetView, false); // Create the per-frame objects this.mFrameObjects = new FrameObject[this.context.kDefaultSwapChainBuffers]; for (int i = 0; i < this.context.kDefaultSwapChainBuffers; i++) { mFrameObjects[i].pCmdAllocator = mpDevice.CreateCommandAllocator(CommandListType.Direct); mFrameObjects[i].pSwapChainBuffer = mpSwapChain.GetBuffer <ID3D12Resource>(i); mFrameObjects[i].rtvHandle = context.CreateRTV(mpDevice, mFrameObjects[i].pSwapChainBuffer, mRtvHeap.Heap, ref mRtvHeap.usedEntries, Format.R8G8B8A8_UNorm_SRgb); } // Create the command-list var cmdList = mpDevice.CreateCommandList(0, CommandListType.Direct, mFrameObjects[0].pCmdAllocator, null); this.mpCmdList = cmdList.QueryInterface <ID3D12GraphicsCommandList4>(); // Create a fence and the event this.mpFence = mpDevice.CreateFence(0, FenceFlags.None); this.mFenceEvent = new EventWaitHandle(false, EventResetMode.AutoReset); }
private ID3D12Resource CreatePlane(ID3D12Device5 device) { Vector3[] vertices = new Vector3[] { new Vector3(-100, -1, -2), new Vector3(100, -1, 100), new Vector3(-100, -1, 100), new Vector3(-100, -1, -2), new Vector3(100, -1, -2), new Vector3(100, -1, 100), }; var res = CreateBuffer(device, vertices.Length * (3 * 4), ResourceFlags.None, ResourceStates.GenericRead, new HeapProperties(HeapType.Upload, CpuPageProperty.Unknown, MemoryPool.Unknown, 0, 0)); IntPtr data = res.Map(0, null); Helpers.CopyMemory <Vector3>(data, new ReadOnlySpan <Vector3>(vertices)); res.Unmap(0, null); return(res); }
public GlobalRootSignature(ID3D12Device5 pDevice, RootSignatureDescription desc) { pRootSig = new Vortice.Direct3D12.GlobalRootSignature(); pRootSig.RootSignature = pDevice.CreateRootSignature(desc, RootSignatureVersion.Version1); suboject = new StateSubObject(pRootSig); }
public unsafe AccelerationStructureBuffers CreateTopLevelAS(ID3D12Device5 pDevice, ID3D12GraphicsCommandList4 pCmdList, AccelerationStructureBuffers[] pBottomLevelAS, ref long tlasSize) { int instances = 2; // First, get the size of the TLAS buffers and create them BuildRaytracingAccelerationStructureInputs inputs = new BuildRaytracingAccelerationStructureInputs(); inputs.Layout = ElementsLayout.Array; inputs.Flags = RaytracingAccelerationStructureBuildFlags.None; inputs.DescriptorsCount = instances; inputs.Type = RaytracingAccelerationStructureType.TopLevel; RaytracingAccelerationStructurePrebuildInfo info; info = pDevice.GetRaytracingAccelerationStructurePrebuildInfo(inputs); // Create the buffers AccelerationStructureBuffers buffers = new AccelerationStructureBuffers(); buffers.pScratch = this.CreateBuffer(pDevice, (uint)info.ScratchDataSizeInBytes, ResourceFlags.AllowUnorderedAccess, ResourceStates.UnorderedAccess, kDefaultHeapProps); buffers.pResult = this.CreateBuffer(pDevice, (uint)info.ResultDataMaxSizeInBytes, ResourceFlags.AllowUnorderedAccess, ResourceStates.RaytracingAccelerationStructure, kDefaultHeapProps); tlasSize = info.ResultDataMaxSizeInBytes; // The instance desc should be inside a buffer, create and map the buffer buffers.pInstanceDesc = this.CreateBuffer(pDevice, (uint)(Unsafe.SizeOf <FixedRaytracingInstanceDescription>() * instances), ResourceFlags.None, ResourceStates.GenericRead, kUploadHeapProps); FixedRaytracingInstanceDescription[] pInstanceDesc = new FixedRaytracingInstanceDescription[instances]; // The transformation matrices for the instances Matrix4x4[] transformation = new Matrix4x4[instances]; transformation[0] = Matrix4x4.CreateTranslation(new Vector3(0, -1.0f, 0)); transformation[1] = Matrix4x4.CreateScale(2.0f); pInstanceDesc[0].InstanceID = 0; // This value will be exposed to the shader via InstanceID() pInstanceDesc[0].InstanceContributionToHitGroupIndex = 0; // This is the offset inside the shader-table. We only have a single geometry, so the offset 0 pInstanceDesc[0].Flags = (byte)RaytracingInstanceFlags.None; pInstanceDesc[0].Transform = Matrix4x4.Transpose(transformation[0]).ToMatrix3x4(); // GLM is column major, the INSTANCE_DESC is row major pInstanceDesc[0].AccelerationStructure = pBottomLevelAS[0].pResult.GPUVirtualAddress; pInstanceDesc[0].InstanceMask = 0xff; for (int i = 1; i < instances; i++) { pInstanceDesc[i].InstanceID = i; // This value will be exposed to the shader via InstanceID() pInstanceDesc[i].InstanceContributionToHitGroupIndex = 0; // This is the offset inside the shader-table. We only have a single geometry, so the offset 0 pInstanceDesc[i].Flags = (byte)RaytracingInstanceFlags.None; pInstanceDesc[i].Transform = Matrix4x4.Transpose(transformation[i]).ToMatrix3x4(); // GLM is column major, the INSTANCE_DESC is row major pInstanceDesc[i].AccelerationStructure = pBottomLevelAS[1].pResult.GPUVirtualAddress; pInstanceDesc[i].InstanceMask = 0xff; } IntPtr data; data = buffers.pInstanceDesc.Map(0, null); Helpers.MemCpy(data, pInstanceDesc, (uint)(Unsafe.SizeOf <FixedRaytracingInstanceDescription>() * instances)); buffers.pInstanceDesc.Unmap(0, null); // Create the TLAS BuildRaytracingAccelerationStructureDescription asDesc = new BuildRaytracingAccelerationStructureDescription(); asDesc.Inputs = inputs; asDesc.Inputs.InstanceDescriptions = buffers.pInstanceDesc.GPUVirtualAddress; asDesc.DestinationAccelerationStructureData = buffers.pResult.GPUVirtualAddress; asDesc.ScratchAccelerationStructureData = buffers.pScratch.GPUVirtualAddress; pCmdList.BuildRaytracingAccelerationStructure(asDesc); // We need to insert a UAV barrier before using the acceleration structures in a raytracing operation ResourceBarrier uavBarrier = new ResourceBarrier(new ResourceUnorderedAccessViewBarrier(buffers.pResult)); pCmdList.ResourceBarrier(uavBarrier); return(buffers); }
public AccelerationStructureBuffers CreatePlaneBottomLevelAS(ID3D12Device5 pDevice, ID3D12GraphicsCommandList4 pCmdList) { this.CreatePrimitive(PrimitiveType.Quad, pDevice, out ID3D12Resource planeVertexBuffer, out uint planeVertexCount, out ID3D12Resource planeIndexBuffer, out uint planeIndexCount); return(this.CreateBottomLevelAS(pDevice, pCmdList, planeVertexBuffer, planeVertexCount, planeIndexBuffer, planeIndexCount)); }
private void CreateTopLevelAS(ID3D12Device5 device, ID3D12GraphicsCommandList4 commandList, ID3D12Resource[] bottomLevelAS, ref long tlasSize, bool isUpdate, float rotate) { int instanceCount = 3; BuildRaytracingAccelerationStructureInputs inputs = new BuildRaytracingAccelerationStructureInputs(); inputs.Layout = ElementsLayout.Array; inputs.Flags = RaytracingAccelerationStructureBuildFlags.AllowUpdate; inputs.DescriptorsCount = instanceCount; inputs.Type = RaytracingAccelerationStructureType.TopLevel; var info = device.GetRaytracingAccelerationStructurePrebuildInfo(inputs); if (isUpdate == false) { HeapProperties properties = new HeapProperties(HeapType.Default, CpuPageProperty.Unknown, MemoryPool.Unknown, 0, 0); HeapProperties upload_properties = new HeapProperties(HeapType.Upload, CpuPageProperty.Unknown, MemoryPool.Unknown, 0, 0); long descSize = (long)Unsafe.SizeOf <MyRaytracingInstanceDescription>(); buffers = new AccelerationStructureBuffers(); buffers.Scratch = CreateBuffer(device, info.ScratchDataSizeInBytes, ResourceFlags.AllowUnorderedAccess, ResourceStates.UnorderedAccess, properties); buffers.Result = CreateBuffer(device, info.ResultDataMaxSizeInBytes, ResourceFlags.AllowUnorderedAccess, ResourceStates.RaytracingAccelerationStructure, properties); buffers.InstanceDesc = CreateBuffer(device, descSize * instanceCount, ResourceFlags.None, ResourceStates.GenericRead, upload_properties); tlasSize = info.ResultDataMaxSizeInBytes; } else { InsertUAVResourceBarrier(buffers.Result); } int instanceContr = 0; MyRaytracingInstanceDescription[] instanceDescs = new MyRaytracingInstanceDescription[instanceCount]; for (int i = 0; i < instanceCount; i++) { instanceDescs[i] = new MyRaytracingInstanceDescription(); float xPos = (i - 1) * 1.5f; float yPos = 0.0f; float zPos = 0.0f; instanceDescs[i].Transform = Matrix4x4.Identity; if (i != 1) { instanceDescs[i].Transform *= Matrix4x4.CreateRotationY(rotate); if (i == 2) { zPos = -0.5f; } } instanceDescs[i].Transform *= Matrix4x4.CreateTranslation(xPos, yPos, zPos); instanceDescs[i].Transform = Matrix4x4.Transpose(instanceDescs[i].Transform); instanceDescs[i].InstanceID = i; instanceDescs[i].InstanceContributionToHitGroupIndex = instanceContr; instanceDescs[i].Flags = (byte)RaytracingInstanceFlags.None; instanceDescs[i].InstanceMask = 0xFF; if (i == 1) { instanceDescs[i].AccelerationStructure = bottomLevelAS[0].GPUVirtualAddress; instanceContr += 4; } else { instanceDescs[i].AccelerationStructure = bottomLevelAS[1].GPUVirtualAddress; instanceContr += 2; } } IntPtr data = buffers.InstanceDesc.Map(0, null); Helpers.CopyMemory <MyRaytracingInstanceDescription>(data, new ReadOnlySpan <MyRaytracingInstanceDescription>( instanceDescs)); buffers.InstanceDesc.Unmap(0, null); BuildRaytracingAccelerationStructureDescription asDesc = new BuildRaytracingAccelerationStructureDescription(); asDesc.Inputs = inputs; asDesc.Inputs.InstanceDescriptions = buffers.InstanceDesc.GPUVirtualAddress; asDesc.DestinationAccelerationStructureData = buffers.Result.GPUVirtualAddress; asDesc.ScratchAccelerationStructureData = buffers.Scratch.GPUVirtualAddress; if (isUpdate) { asDesc.Inputs.Flags |= RaytracingAccelerationStructureBuildFlags.PerformUpdate; asDesc.SourceAccelerationStructureData = buffers.Result.GPUVirtualAddress; } commandList.BuildRaytracingAccelerationStructure(asDesc); InsertUAVResourceBarrier(buffers.Result); }
public unsafe void LoadGLTF(string filePath, ID3D12Device5 pDevice, out ID3D12Resource vertexBuffer, out uint vertexCount, out ID3D12Resource indexBuffer, out uint indexCount) { using (var stream = File.OpenRead(filePath)) { if (stream == null || !stream.CanRead) { throw new ArgumentException("Invalid parameter. Stream must be readable", "imageStream"); } var model = Interface.LoadModel(stream); // read all buffers int numBuffers = model.Buffers.Length; var buffers = new BufferInfo[numBuffers]; for (int i = 0; i < numBuffers; ++i) { var bufferBytes = model.LoadBinaryBuffer(i, filePath); buffers[i] = new BufferInfo(bufferBytes); } // Read only first mesh and first primitive var mesh = model.Meshes[0]; var primitive = mesh.Primitives[0]; // Create Vertex Buffer var attributes = primitive.Attributes.ToArray(); Vector3[] positions = new Vector3[0]; Vector3[] normals = new Vector3[0]; Vector2[] texcoords = new Vector2[0]; Vector3[] tangents = new Vector3[0]; for (int i = 0; i < attributes.Length; i++) { var attributeAccessor = model.Accessors[attributes[i].Value]; var attributebufferView = model.BufferViews[attributeAccessor.BufferView.Value]; IntPtr attributePointer = buffers[attributebufferView.Buffer].bufferPointer + attributebufferView.ByteOffset + attributeAccessor.ByteOffset; string attributeKey = attributes[i].Key; if (attributeKey.Contains("POSITION")) { this.AttributeCopyData(ref positions, attributeAccessor.Count * Unsafe.SizeOf <Vector3>(), attributePointer); } else if (attributeKey.Contains("NORMAL")) { this.AttributeCopyData(ref normals, attributeAccessor.Count * Unsafe.SizeOf <Vector3>(), attributePointer); } else if (attributeKey.Contains("TANGENT")) { this.AttributeCopyData(ref tangents, attributeAccessor.Count * Unsafe.SizeOf <Vector3>(), attributePointer); } else if (attributeKey.Contains("TEXCOORD")) { this.AttributeCopyData(ref texcoords, attributeAccessor.Count * Unsafe.SizeOf <Vector2>(), attributePointer); } } VertexPositionNormalTangentTexture[] vertexData = new VertexPositionNormalTangentTexture[positions.Length]; for (int i = 0; i < vertexData.Length; i++) { Vector3 position = positions[i]; Vector3 normal = (normals.Length > i) ? normals[i] : Vector3.Zero; Vector2 texcoord = (texcoords.Length > i) ? texcoords[i] : Vector2.Zero; Vector3 tangent = (tangents.Length > i) ? tangents[i] : Vector3.Zero; vertexData[i] = new VertexPositionNormalTangentTexture(position, normal, tangent, texcoord); } vertexCount = (uint)vertexData.Length; vertexBuffer = CreateBuffer(pDevice, (uint)(Unsafe.SizeOf <VertexPositionNormalTangentTexture>() * vertexData.Length), ResourceFlags.None, ResourceStates.GenericRead, kUploadHeapProps); IntPtr pData = vertexBuffer.Map(0, null); Helpers.MemCpy(pData, vertexData, (uint)(Unsafe.SizeOf <VertexPositionNormalTangentTexture>() * vertexData.Length)); vertexBuffer.Unmap(0, null); // Create Index buffer var indicesAccessor = model.Accessors[primitive.Indices.Value]; var indicesbufferView = model.BufferViews[indicesAccessor.BufferView.Value]; IntPtr indicesPointer = buffers[indicesbufferView.Buffer].bufferPointer + indicesbufferView.ByteOffset + indicesAccessor.ByteOffset; indexCount = (uint)indicesAccessor.Count; indexBuffer = CreateBuffer(pDevice, (uint)indicesAccessor.Count * sizeof(ushort), ResourceFlags.None, ResourceStates.GenericRead, kUploadHeapProps); IntPtr pIB = indexBuffer.Map(0, null); Unsafe.CopyBlock((void *)pIB, (void *)indicesPointer, (uint)indicesAccessor.Count * sizeof(ushort)); indexBuffer.Unmap(0, null); for (int i = 0; i < numBuffers; ++i) { buffers[i].Dispose(); } buffers = null; } }
internal MyGlobalRootSignature(ID3D12Device5 device, RootSignatureDescription desc) { rootSig = new GlobalRootSignature(); rootSig.RootSignature = device.CreateRootSignature(desc, RootSignatureVersion.Version1); subObject = new StateSubObject(rootSig); }
public unsafe AccelerationStructureBuffers BuildTopLevelAS(ID3D12Device5 pDevice, ID3D12GraphicsCommandList4 pCmdList, ID3D12Resource[] pBottomLevelAS, ref long tlasSize, float rotation, bool update, ref AccelerationStructureBuffers buffers) { // First, get the size of the TLAS buffers and create them BuildRaytracingAccelerationStructureInputs inputs = new BuildRaytracingAccelerationStructureInputs(); inputs.Layout = ElementsLayout.Array; inputs.Flags = RaytracingAccelerationStructureBuildFlags.AllowUpdate; inputs.DescriptorsCount = 3; // NumDescs inputs.Type = RaytracingAccelerationStructureType.TopLevel; RaytracingAccelerationStructurePrebuildInfo info; info = pDevice.GetRaytracingAccelerationStructurePrebuildInfo(inputs); if (update) { // If this a request for an update, then the TLAS was already used in a DispatchRay() call. We need a UAV barrier to make sure the read operation ends before updating the buffer ResourceBarrier uavBarrier1 = new ResourceBarrier(new ResourceUnorderedAccessViewBarrier(buffers.pResult)); pCmdList.ResourceBarrier(uavBarrier1); } else { buffers.pScratch = this.CreateBuffer(pDevice, (uint)info.ScratchDataSizeInBytes, ResourceFlags.AllowUnorderedAccess, ResourceStates.UnorderedAccess, kDefaultHeapProps); buffers.pResult = this.CreateBuffer(pDevice, (uint)info.ResultDataMaxSizeInBytes, ResourceFlags.AllowUnorderedAccess, ResourceStates.RaytracingAccelerationStructure, kDefaultHeapProps); buffers.pInstanceDesc = this.CreateBuffer(pDevice, (uint)Unsafe.SizeOf <FixedRaytracingInstanceDescription>() * 3, ResourceFlags.None, ResourceStates.GenericRead, kUploadHeapProps); tlasSize = info.ResultDataMaxSizeInBytes; } FixedRaytracingInstanceDescription[] instanceDescs = new FixedRaytracingInstanceDescription[3]; // The transformation matrices for the instances Matrix4x4[] transformation = new Matrix4x4[3]; Matrix4x4 rotationMat = Matrix4x4.CreateRotationY(rotation); transformation[0] = Matrix4x4.Identity; transformation[1] = rotationMat * Matrix4x4.CreateTranslation(new Vector3(-2, 0, 0)); transformation[2] = rotationMat * Matrix4x4.CreateTranslation(new Vector3(2, 0, 0)); // The InstanceContributionToHitGroupIndex is set based on the shader-table layout specified in createShaderTable() // Create the desc for the triangle/plane instance instanceDescs[0].InstanceID = 0; instanceDescs[0].InstanceContributionToHitGroupIndex = 0; instanceDescs[0].Flags = (byte)RaytracingInstanceFlags.None; instanceDescs[0].Transform = Matrix4x4.Transpose(transformation[0]).ToMatrix3x4(); // GLM is column major, the INSTANCE_DESC is row major instanceDescs[0].AccelerationStructure = pBottomLevelAS[0].GPUVirtualAddress; instanceDescs[0].InstanceMask = 0xFF; for (int i = 1; i < 3; i++) { instanceDescs[i].InstanceID = i; // This value will be exposed to the shader via InstanceID() instanceDescs[i].InstanceContributionToHitGroupIndex = (i * 2) + 2; // The plane takes an additional entry in the shader-table, hence the +1 instanceDescs[i].Flags = (byte)RaytracingInstanceFlags.None; instanceDescs[i].Transform = Matrix4x4.Transpose(transformation[i]).ToMatrix3x4(); // GLM is column major, the INSTANCE_DESC is row major instanceDescs[i].AccelerationStructure = pBottomLevelAS[1].GPUVirtualAddress; instanceDescs[i].InstanceMask = 0xFF; } // Map the instance desc buffer IntPtr data; data = buffers.pInstanceDesc.Map(0, null); Helpers.MemCpy(data, instanceDescs, (uint)Unsafe.SizeOf <FixedRaytracingInstanceDescription>() * 3); buffers.pInstanceDesc.Unmap(0, null); // Create the TLAS BuildRaytracingAccelerationStructureDescription asDesc = new BuildRaytracingAccelerationStructureDescription(); asDesc.Inputs = inputs; asDesc.Inputs.InstanceDescriptions = buffers.pInstanceDesc.GPUVirtualAddress; asDesc.DestinationAccelerationStructureData = buffers.pResult.GPUVirtualAddress; asDesc.ScratchAccelerationStructureData = buffers.pScratch.GPUVirtualAddress; // If this is an update operation, set the source buffer and the perform_update flag if (update) { asDesc.Inputs.Flags |= RaytracingAccelerationStructureBuildFlags.PerformUpdate; asDesc.SourceAccelerationStructureData = buffers.pResult.GPUVirtualAddress; } pCmdList.BuildRaytracingAccelerationStructure(asDesc); // We need to insert a UAV barrier before using the acceleration structures in a raytracing operation ResourceBarrier uavBarrier = new ResourceBarrier(new ResourceUnorderedAccessViewBarrier(buffers.pResult)); pCmdList.ResourceBarrier(uavBarrier); return(buffers); }