public ShaderResourceView GenerateNoiseTexture(Buffer constantBuffer, DirectComputeConstantBuffer container)
        {
            Texture3D noiseTexture = new Texture3D(graphicsDevice, new Texture3DDescription()
            {
                BindFlags = BindFlags.ShaderResource | BindFlags.UnorderedAccess,
                CpuAccessFlags = CpuAccessFlags.None,
                Format = Format.R32_Float,
                MipLevels = 1,
                OptionFlags = ResourceOptionFlags.None,
                Usage = ResourceUsage.Default,
                Width = container.Width,
                Height = container.Height,
                Depth = container.Depth
            });

            UnorderedAccessView noiseTextureUAV = new UnorderedAccessView(graphicsDevice, noiseTexture);

            DataBox data = graphicsDevice.ImmediateContext.MapSubresource(constantBuffer, MapMode.WriteDiscard, MapFlags.None);
            data.Data.Write<DirectComputeConstantBuffer>(container);
            graphicsDevice.ImmediateContext.UnmapSubresource(constantBuffer, 0);

            graphicsDevice.ImmediateContext.ComputeShader.Set(computeFillNoiseTexture);
            graphicsDevice.ImmediateContext.ComputeShader.SetConstantBuffer(constantBuffer, 0);
            graphicsDevice.ImmediateContext.ComputeShader.SetUnorderedAccessView(noiseTextureUAV, 0);

            Vector3 gridDim = new Vector3((float)Math.Ceiling(container.Width / 8.0f), (float)Math.Ceiling(container.Height / 8.0f), (float)Math.Ceiling(container.Depth / 8.0f));

            graphicsDevice.ImmediateContext.Dispatch((int)gridDim.X, (int)gridDim.Y, (int)gridDim.Z);

            noiseTextureUAV.Dispose();

            return new ShaderResourceView(graphicsDevice, noiseTexture);
        }
Пример #2
0
        public ShaderResourceView GenerateNoiseTexture(Buffer constantBuffer, DirectComputeConstantBuffer container)
        {
            Texture3D noiseTexture = new Texture3D(graphicsDevice, new Texture3DDescription()
            {
                BindFlags      = BindFlags.ShaderResource | BindFlags.UnorderedAccess,
                CpuAccessFlags = CpuAccessFlags.None,
                Format         = Format.R32_Float,
                MipLevels      = 1,
                OptionFlags    = ResourceOptionFlags.None,
                Usage          = ResourceUsage.Default,
                Width          = container.Width,
                Height         = container.Height,
                Depth          = container.Depth
            });

            UnorderedAccessView noiseTextureUAV = new UnorderedAccessView(graphicsDevice, noiseTexture);

            DataBox data = graphicsDevice.ImmediateContext.MapSubresource(constantBuffer, MapMode.WriteDiscard, MapFlags.None);

            data.Data.Write <DirectComputeConstantBuffer>(container);
            graphicsDevice.ImmediateContext.UnmapSubresource(constantBuffer, 0);

            graphicsDevice.ImmediateContext.ComputeShader.Set(computeFillNoiseTexture);
            graphicsDevice.ImmediateContext.ComputeShader.SetConstantBuffer(constantBuffer, 0);
            graphicsDevice.ImmediateContext.ComputeShader.SetUnorderedAccessView(noiseTextureUAV, 0);

            Vector3 gridDim = new Vector3((float)Math.Ceiling(container.Width / 8.0f), (float)Math.Ceiling(container.Height / 8.0f), (float)Math.Ceiling(container.Depth / 8.0f));

            graphicsDevice.ImmediateContext.Dispatch((int)gridDim.X, (int)gridDim.Y, (int)gridDim.Z);

            noiseTextureUAV.Dispose();

            return(new ShaderResourceView(graphicsDevice, noiseTexture));
        }
        public UnorderedAccessView PrefixSumArray(Buffer constantBuffer, UnorderedAccessView trisCountUAV)
        {
            int arrayLength = trisCountUAV.Description.ElementCount;
            int batchSize = trisCountUAV.Description.ElementCount / arrayLength;

            if (!IsPowerOfTwo(trisCountUAV.Description.ElementCount))
                throw new Exception("Input array length is not power of two.");

            Buffer buffer = new Buffer(graphicsDevice, new BufferDescription()
            {
                BindFlags = BindFlags.UnorderedAccess,
                CpuAccessFlags = CpuAccessFlags.None,
                OptionFlags = ResourceOptionFlags.StructuredBuffer,
                Usage = ResourceUsage.Default,
                SizeInBytes = Marshal.SizeOf(typeof(int)) * trisCountUAV.Description.ElementCount,
                StructureByteStride = Marshal.SizeOf(typeof(int))
            });

            UnorderedAccessView bufferUAV = new UnorderedAccessView(graphicsDevice, buffer);

            Buffer output = new Buffer(graphicsDevice, new BufferDescription()
            {
                BindFlags = BindFlags.UnorderedAccess,
                CpuAccessFlags = CpuAccessFlags.None,
                OptionFlags = ResourceOptionFlags.StructuredBuffer,
                Usage = ResourceUsage.Default,
                SizeInBytes = Marshal.SizeOf(typeof(int)) * trisCountUAV.Description.ElementCount,
                StructureByteStride = Marshal.SizeOf(typeof(int))
            });

            UnorderedAccessView outputUAV = new UnorderedAccessView(graphicsDevice, output);

            DirectComputeConstantBuffer constantBufferContainer = new DirectComputeConstantBuffer()
            {
                PrefixSize = 4 * threadBlockSize,
                PrefixN = (batchSize * arrayLength) / (4 * threadBlockSize),
                PrefixArrayLength = arrayLength / (4 * threadBlockSize)
            };

            DataBox data = graphicsDevice.ImmediateContext.MapSubresource(constantBuffer, MapMode.WriteDiscard, MapFlags.None);
            data.Data.Write<DirectComputeConstantBuffer>(constantBufferContainer);
            graphicsDevice.ImmediateContext.UnmapSubresource(constantBuffer, 0);

            Vector3 gridDim = new Vector3((batchSize * arrayLength) / (4 * threadBlockSize), 1, 1);
            Vector3 gridDimShared2 = new Vector3((int)Math.Ceiling(((batchSize * arrayLength) / (4 * threadBlockSize)) / (double)threadBlockSize), 1, 1);

            graphicsDevice.ImmediateContext.ComputeShader.Set(computeScanExclusiveShared);
            graphicsDevice.ImmediateContext.ComputeShader.SetConstantBuffer(constantBuffer, 0);
            graphicsDevice.ImmediateContext.ComputeShader.SetUnorderedAccessView(trisCountUAV, 2);
            graphicsDevice.ImmediateContext.ComputeShader.SetUnorderedAccessView(outputUAV, 3);
            graphicsDevice.ImmediateContext.ComputeShader.SetUnorderedAccessView(bufferUAV, 4);

            graphicsDevice.ImmediateContext.Dispatch((int)gridDim.X, (int)gridDim.Y, (int)gridDim.Z);
            
            graphicsDevice.ImmediateContext.ComputeShader.Set(computeScanExclusiveShared2);

            graphicsDevice.ImmediateContext.Dispatch((int)gridDimShared2.X, (int)gridDimShared2.Y, (int)gridDimShared2.Z);

            graphicsDevice.ImmediateContext.ComputeShader.Set(computeUniformUpdate);

            graphicsDevice.ImmediateContext.Dispatch((int)gridDim.X, (int)gridDim.Y, (int)gridDim.Z);

            buffer.Dispose();
            bufferUAV.Dispose();

            return outputUAV;
        }
Пример #4
0
        private void Generate(ComputeShader computePositionWeight, int width, int height, int depth)
        {
            int count   = width * height * depth;
            int widthD  = width - 1;
            int heightD = height - 1;
            int depthD  = depth - 1;
            int countD  = widthD * heightD * depthD;

            int nearestW     = NearestPowerOfTwo(widthD);
            int nearestH     = NearestPowerOfTwo(heightD);
            int nearestD     = NearestPowerOfTwo(depthD);
            int nearestCount = nearestW * nearestH * nearestD;

            Vector3 gridDim  = new Vector3((float)Math.Ceiling(width / 8.0f), (float)Math.Ceiling(height / 8.0f), (float)Math.Ceiling(depth / 8.0f));
            Vector3 gridDimD = new Vector3((float)Math.Ceiling(widthD / 8.0f), (float)Math.Ceiling(heightD / 8.0f), (float)Math.Ceiling(depthD / 8.0f));

            constantBufferContainer = new DirectComputeConstantBuffer()
            {
                Width  = 16,
                Height = 16,
                Depth  = 16,
                Seed   = (int)DateTime.Now.Ticks
            };

            DirectComputeNoiseCube noiseCube = new DirectComputeNoiseCube(graphicsDevice);

            ShaderResourceView noiseSRV = noiseCube.GenerateNoiseTexture(constantBuffer, constantBufferContainer);

            Buffer voxelsBuffer = new Buffer(graphicsDevice, new BufferDescription()
            {
                BindFlags           = BindFlags.UnorderedAccess,
                CpuAccessFlags      = CpuAccessFlags.None,
                OptionFlags         = ResourceOptionFlags.StructuredBuffer,
                Usage               = ResourceUsage.Default,
                SizeInBytes         = Marshal.SizeOf(typeof(Voxel)) * count,
                StructureByteStride = Marshal.SizeOf(typeof(Voxel))
            });

            UnorderedAccessView voxelsUAV = new UnorderedAccessView(graphicsDevice, voxelsBuffer);

            constantBufferContainer = new DirectComputeConstantBuffer()
            {
                Width               = width,
                Height              = height,
                Depth               = depth,
                AmbientRayWidth     = container.Settings.AmbientRayWidth,
                AmbientSamplesCount = container.Settings.AmbientSamplesCount,
                NearestWidth        = nearestW,
                NearestHeight       = nearestH,
                NearestDepth        = nearestD
            };

            DataBox data = graphicsDevice.ImmediateContext.MapSubresource(constantBuffer, MapMode.WriteDiscard, MapFlags.None);

            data.Data.Write <DirectComputeConstantBuffer>(constantBufferContainer);
            graphicsDevice.ImmediateContext.UnmapSubresource(constantBuffer, 0);

            graphicsDevice.ImmediateContext.ComputeShader.Set(computePositionWeight);
            graphicsDevice.ImmediateContext.ComputeShader.SetConstantBuffer(constantBuffer, 0);
            graphicsDevice.ImmediateContext.ComputeShader.SetUnorderedAccessView(voxelsUAV, 0);
            graphicsDevice.ImmediateContext.ComputeShader.SetShaderResource(noiseSRV, 0);

            graphicsDevice.ImmediateContext.Dispatch((int)gridDim.X, (int)gridDim.Y, (int)gridDim.Z);

            graphicsDevice.ImmediateContext.ComputeShader.Set(computeNormalAmbient);

            graphicsDevice.ImmediateContext.Dispatch((int)gridDim.X, (int)gridDim.Y, (int)gridDim.Z);

            Buffer offsetsBuffer = new Buffer(graphicsDevice, new BufferDescription()
            {
                BindFlags           = BindFlags.UnorderedAccess,
                CpuAccessFlags      = CpuAccessFlags.None,
                OptionFlags         = ResourceOptionFlags.StructuredBuffer,
                Usage               = ResourceUsage.Default,
                SizeInBytes         = Marshal.SizeOf(typeof(int)) * countD,
                StructureByteStride = Marshal.SizeOf(typeof(int))
            });

            UnorderedAccessView offsetsUAV = new UnorderedAccessView(graphicsDevice, offsetsBuffer);

            Buffer trisCountBuffer = new Buffer(graphicsDevice, new BufferDescription()
            {
                BindFlags           = BindFlags.UnorderedAccess,
                CpuAccessFlags      = CpuAccessFlags.None,
                OptionFlags         = ResourceOptionFlags.StructuredBuffer,
                Usage               = ResourceUsage.Default,
                SizeInBytes         = Marshal.SizeOf(typeof(int)) * nearestCount,
                StructureByteStride = Marshal.SizeOf(typeof(int))
            });

            UnorderedAccessView trisCountUAV = new UnorderedAccessView(graphicsDevice, trisCountBuffer);

            graphicsDevice.ImmediateContext.ClearUnorderedAccessView(trisCountUAV, new int[] { 0, 0, 0, 0 });

            graphicsDevice.ImmediateContext.ComputeShader.Set(computeMarchingCubesCases);
            graphicsDevice.ImmediateContext.ComputeShader.SetUnorderedAccessView(offsetsUAV, 1);
            graphicsDevice.ImmediateContext.ComputeShader.SetUnorderedAccessView(trisCountUAV, 2);

            graphicsDevice.ImmediateContext.Dispatch((int)gridDimD.X, (int)gridDimD.Y, (int)gridDimD.Z);

            UnorderedAccessView prefixSumsUAV = prefixScan.PrefixSumArray(constantBuffer, trisCountUAV);

            int lastTrisCount = DirectComputeBufferHelper.CopyBuffer <int>(graphicsDevice, trisCountBuffer, nearestCount - 1, 1)[0];

            int lastPrefixSum = DirectComputeBufferHelper.CopyBuffer <int>(graphicsDevice, prefixSumsUAV.Resource, nearestCount - 1, 1)[0];

            int totalVerticesCount = (lastTrisCount + lastPrefixSum) * 3;

            if (totalVerticesCount > 0)
            {
                if (container.Geometry != null)
                {
                    container.Geometry.Dispose();
                }

                container.VertexCount = totalVerticesCount;

                container.Geometry = new Buffer(graphicsDevice, new BufferDescription()
                {
                    BindFlags      = BindFlags.VertexBuffer,
                    CpuAccessFlags = CpuAccessFlags.None,
                    OptionFlags    = ResourceOptionFlags.None,
                    SizeInBytes    = Marshal.SizeOf(typeof(VoxelMeshVertex)) * totalVerticesCount,
                    Usage          = ResourceUsage.Default
                });

                Buffer verticesBuffer = new Buffer(graphicsDevice, new BufferDescription()
                {
                    BindFlags           = BindFlags.UnorderedAccess,
                    CpuAccessFlags      = CpuAccessFlags.None,
                    OptionFlags         = ResourceOptionFlags.StructuredBuffer,
                    Usage               = ResourceUsage.Default,
                    SizeInBytes         = Marshal.SizeOf(typeof(VoxelMeshVertex)) * totalVerticesCount,
                    StructureByteStride = Marshal.SizeOf(typeof(VoxelMeshVertex))
                });

                UnorderedAccessView verticesUAV = new UnorderedAccessView(graphicsDevice, verticesBuffer);

                constantBufferContainer = new DirectComputeConstantBuffer()
                {
                    Width         = width,
                    Height        = height,
                    Depth         = depth,
                    NearestWidth  = nearestW,
                    NearestHeight = nearestH,
                    NearestDepth  = nearestD
                };

                data = graphicsDevice.ImmediateContext.MapSubresource(constantBuffer, MapMode.WriteDiscard, MapFlags.None);
                data.Data.Write <DirectComputeConstantBuffer>(constantBufferContainer);
                graphicsDevice.ImmediateContext.UnmapSubresource(constantBuffer, 0);

                graphicsDevice.ImmediateContext.ComputeShader.Set(computeMarchingCubesVertices);
                graphicsDevice.ImmediateContext.ComputeShader.SetUnorderedAccessView(trisCountUAV, 2);
                graphicsDevice.ImmediateContext.ComputeShader.SetUnorderedAccessView(prefixSumsUAV, 3);
                graphicsDevice.ImmediateContext.ComputeShader.SetUnorderedAccessView(verticesUAV, 5);

                graphicsDevice.ImmediateContext.Dispatch((int)gridDimD.X, (int)gridDimD.Y, (int)gridDimD.Z);

                graphicsDevice.ImmediateContext.CopyResource(verticesBuffer, container.Geometry);

                verticesUAV.Dispose();
                verticesBuffer.Dispose();
            }
            else
            {
                container.VertexCount = 0;

                if (container.Geometry != null)
                {
                    container.Geometry.Dispose();
                }
            }

            for (int i = 0; i <= 5; i++)
            {
                graphicsDevice.ImmediateContext.ComputeShader.SetUnorderedAccessView(null, i);
            }

            prefixSumsUAV.Resource.Dispose();
            prefixSumsUAV.Dispose();
            noiseCube.Dispose();
            noiseSRV.Resource.Dispose();
            noiseSRV.Dispose();
            voxelsBuffer.Dispose();
            voxelsUAV.Dispose();
            offsetsBuffer.Dispose();
            offsetsUAV.Dispose();
            trisCountBuffer.Dispose();
            trisCountUAV.Dispose();
        }
        private void Generate(ComputeShader computePositionWeight, int width, int height, int depth)
        {
            int count = width * height * depth;
            int widthD = width - 1;
            int heightD = height - 1;
            int depthD = depth - 1;
            int countD = widthD * heightD * depthD;

            int nearestW = NearestPowerOfTwo(widthD);
            int nearestH = NearestPowerOfTwo(heightD);
            int nearestD = NearestPowerOfTwo(depthD);
            int nearestCount = nearestW * nearestH * nearestD;

            Vector3 gridDim = new Vector3((float)Math.Ceiling(width / 8.0f), (float)Math.Ceiling(height / 8.0f), (float)Math.Ceiling(depth / 8.0f));
            Vector3 gridDimD = new Vector3((float)Math.Ceiling(widthD / 8.0f), (float)Math.Ceiling(heightD / 8.0f), (float)Math.Ceiling(depthD / 8.0f));

            constantBufferContainer = new DirectComputeConstantBuffer()
            {
                Width = 16,
                Height = 16,
                Depth = 16,
                Seed = (int)DateTime.Now.Ticks
            };

            DirectComputeNoiseCube noiseCube = new DirectComputeNoiseCube(graphicsDevice);

            ShaderResourceView noiseSRV = noiseCube.GenerateNoiseTexture(constantBuffer, constantBufferContainer);

            Buffer voxelsBuffer = new Buffer(graphicsDevice, new BufferDescription()
            {
                BindFlags = BindFlags.UnorderedAccess,
                CpuAccessFlags = CpuAccessFlags.None,
                OptionFlags = ResourceOptionFlags.StructuredBuffer,
                Usage = ResourceUsage.Default,
                SizeInBytes = Marshal.SizeOf(typeof(Voxel)) * count,
                StructureByteStride = Marshal.SizeOf(typeof(Voxel))
            });

            UnorderedAccessView voxelsUAV = new UnorderedAccessView(graphicsDevice, voxelsBuffer);

            constantBufferContainer = new DirectComputeConstantBuffer()
            {
                Width = width,
                Height = height,
                Depth = depth,
                AmbientRayWidth = container.Settings.AmbientRayWidth,
                AmbientSamplesCount = container.Settings.AmbientSamplesCount,
                NearestWidth = nearestW,
                NearestHeight = nearestH,
                NearestDepth = nearestD
            };

            DataBox data = graphicsDevice.ImmediateContext.MapSubresource(constantBuffer, MapMode.WriteDiscard, MapFlags.None);
            data.Data.Write<DirectComputeConstantBuffer>(constantBufferContainer);
            graphicsDevice.ImmediateContext.UnmapSubresource(constantBuffer, 0);

            graphicsDevice.ImmediateContext.ComputeShader.Set(computePositionWeight);
            graphicsDevice.ImmediateContext.ComputeShader.SetConstantBuffer(constantBuffer, 0);
            graphicsDevice.ImmediateContext.ComputeShader.SetUnorderedAccessView(voxelsUAV, 0);
            graphicsDevice.ImmediateContext.ComputeShader.SetShaderResource(noiseSRV, 0);

            graphicsDevice.ImmediateContext.Dispatch((int)gridDim.X, (int)gridDim.Y, (int)gridDim.Z);

            graphicsDevice.ImmediateContext.ComputeShader.Set(computeNormalAmbient);

            graphicsDevice.ImmediateContext.Dispatch((int)gridDim.X, (int)gridDim.Y, (int)gridDim.Z);

            Buffer offsetsBuffer = new Buffer(graphicsDevice, new BufferDescription()
            {
                BindFlags = BindFlags.UnorderedAccess,
                CpuAccessFlags = CpuAccessFlags.None,
                OptionFlags = ResourceOptionFlags.StructuredBuffer,
                Usage = ResourceUsage.Default,
                SizeInBytes = Marshal.SizeOf(typeof(int)) * countD,
                StructureByteStride = Marshal.SizeOf(typeof(int))
            });

            UnorderedAccessView offsetsUAV = new UnorderedAccessView(graphicsDevice, offsetsBuffer);

            Buffer trisCountBuffer = new Buffer(graphicsDevice, new BufferDescription()
            {
                BindFlags = BindFlags.UnorderedAccess,
                CpuAccessFlags = CpuAccessFlags.None,
                OptionFlags = ResourceOptionFlags.StructuredBuffer,
                Usage = ResourceUsage.Default,
                SizeInBytes = Marshal.SizeOf(typeof(int)) * nearestCount,
                StructureByteStride = Marshal.SizeOf(typeof(int))
            });

            UnorderedAccessView trisCountUAV = new UnorderedAccessView(graphicsDevice, trisCountBuffer);

            graphicsDevice.ImmediateContext.ClearUnorderedAccessView(trisCountUAV, new int[] { 0, 0, 0, 0 });

            graphicsDevice.ImmediateContext.ComputeShader.Set(computeMarchingCubesCases);
            graphicsDevice.ImmediateContext.ComputeShader.SetUnorderedAccessView(offsetsUAV, 1);
            graphicsDevice.ImmediateContext.ComputeShader.SetUnorderedAccessView(trisCountUAV, 2);

            graphicsDevice.ImmediateContext.Dispatch((int)gridDimD.X, (int)gridDimD.Y, (int)gridDimD.Z);

            UnorderedAccessView prefixSumsUAV = prefixScan.PrefixSumArray(constantBuffer, trisCountUAV);

            int lastTrisCount = DirectComputeBufferHelper.CopyBuffer<int>(graphicsDevice, trisCountBuffer, nearestCount - 1, 1)[0];

            int lastPrefixSum = DirectComputeBufferHelper.CopyBuffer<int>(graphicsDevice, prefixSumsUAV.Resource, nearestCount - 1, 1)[0];

            int totalVerticesCount = (lastTrisCount + lastPrefixSum) * 3;

            if (totalVerticesCount > 0)
            {
                if (container.Geometry != null)
                    container.Geometry.Dispose();

                container.VertexCount = totalVerticesCount;

                container.Geometry = new Buffer(graphicsDevice, new BufferDescription()
                {
                    BindFlags = BindFlags.VertexBuffer,
                    CpuAccessFlags = CpuAccessFlags.None,
                    OptionFlags = ResourceOptionFlags.None,
                    SizeInBytes = Marshal.SizeOf(typeof(VoxelMeshVertex)) * totalVerticesCount,
                    Usage = ResourceUsage.Default
                });

                Buffer verticesBuffer = new Buffer(graphicsDevice, new BufferDescription()
                {
                    BindFlags = BindFlags.UnorderedAccess,
                    CpuAccessFlags = CpuAccessFlags.None,
                    OptionFlags = ResourceOptionFlags.StructuredBuffer,
                    Usage = ResourceUsage.Default,
                    SizeInBytes = Marshal.SizeOf(typeof(VoxelMeshVertex)) * totalVerticesCount,
                    StructureByteStride = Marshal.SizeOf(typeof(VoxelMeshVertex))
                });

                UnorderedAccessView verticesUAV = new UnorderedAccessView(graphicsDevice, verticesBuffer);

                constantBufferContainer = new DirectComputeConstantBuffer()
                {
                    Width = width,
                    Height = height,
                    Depth = depth,
                    NearestWidth = nearestW,
                    NearestHeight = nearestH,
                    NearestDepth = nearestD
                };

                data = graphicsDevice.ImmediateContext.MapSubresource(constantBuffer, MapMode.WriteDiscard, MapFlags.None);
                data.Data.Write<DirectComputeConstantBuffer>(constantBufferContainer);
                graphicsDevice.ImmediateContext.UnmapSubresource(constantBuffer, 0);

                graphicsDevice.ImmediateContext.ComputeShader.Set(computeMarchingCubesVertices);
                graphicsDevice.ImmediateContext.ComputeShader.SetUnorderedAccessView(trisCountUAV, 2);
                graphicsDevice.ImmediateContext.ComputeShader.SetUnorderedAccessView(prefixSumsUAV, 3);
                graphicsDevice.ImmediateContext.ComputeShader.SetUnorderedAccessView(verticesUAV, 5);

                graphicsDevice.ImmediateContext.Dispatch((int)gridDimD.X, (int)gridDimD.Y, (int)gridDimD.Z);

                graphicsDevice.ImmediateContext.CopyResource(verticesBuffer, container.Geometry);

                verticesUAV.Dispose();
                verticesBuffer.Dispose();
            }
            else
            {
                container.VertexCount = 0;

                if (container.Geometry != null)
                    container.Geometry.Dispose();
            }

            for (int i = 0; i <= 5; i++)
            {
                graphicsDevice.ImmediateContext.ComputeShader.SetUnorderedAccessView(null, i);
            }

            prefixSumsUAV.Resource.Dispose();
            prefixSumsUAV.Dispose();
            noiseCube.Dispose();
            noiseSRV.Resource.Dispose();
            noiseSRV.Dispose();
            voxelsBuffer.Dispose();
            voxelsUAV.Dispose();
            offsetsBuffer.Dispose();
            offsetsUAV.Dispose();
            trisCountBuffer.Dispose();
            trisCountUAV.Dispose();
        }
        public UnorderedAccessView PrefixSumArray(Buffer constantBuffer, UnorderedAccessView trisCountUAV)
        {
            int arrayLength = trisCountUAV.Description.ElementCount;
            int batchSize   = trisCountUAV.Description.ElementCount / arrayLength;

            if (!IsPowerOfTwo(trisCountUAV.Description.ElementCount))
            {
                throw new Exception("Input array length is not power of two.");
            }

            Buffer buffer = new Buffer(graphicsDevice, new BufferDescription()
            {
                BindFlags           = BindFlags.UnorderedAccess,
                CpuAccessFlags      = CpuAccessFlags.None,
                OptionFlags         = ResourceOptionFlags.StructuredBuffer,
                Usage               = ResourceUsage.Default,
                SizeInBytes         = Marshal.SizeOf(typeof(int)) * trisCountUAV.Description.ElementCount,
                StructureByteStride = Marshal.SizeOf(typeof(int))
            });

            UnorderedAccessView bufferUAV = new UnorderedAccessView(graphicsDevice, buffer);

            Buffer output = new Buffer(graphicsDevice, new BufferDescription()
            {
                BindFlags           = BindFlags.UnorderedAccess,
                CpuAccessFlags      = CpuAccessFlags.None,
                OptionFlags         = ResourceOptionFlags.StructuredBuffer,
                Usage               = ResourceUsage.Default,
                SizeInBytes         = Marshal.SizeOf(typeof(int)) * trisCountUAV.Description.ElementCount,
                StructureByteStride = Marshal.SizeOf(typeof(int))
            });

            UnorderedAccessView outputUAV = new UnorderedAccessView(graphicsDevice, output);

            DirectComputeConstantBuffer constantBufferContainer = new DirectComputeConstantBuffer()
            {
                PrefixSize        = 4 * threadBlockSize,
                PrefixN           = (batchSize * arrayLength) / (4 * threadBlockSize),
                PrefixArrayLength = arrayLength / (4 * threadBlockSize)
            };

            DataBox data = graphicsDevice.ImmediateContext.MapSubresource(constantBuffer, MapMode.WriteDiscard, MapFlags.None);

            data.Data.Write <DirectComputeConstantBuffer>(constantBufferContainer);
            graphicsDevice.ImmediateContext.UnmapSubresource(constantBuffer, 0);

            Vector3 gridDim        = new Vector3((batchSize * arrayLength) / (4 * threadBlockSize), 1, 1);
            Vector3 gridDimShared2 = new Vector3((int)Math.Ceiling(((batchSize * arrayLength) / (4 * threadBlockSize)) / (double)threadBlockSize), 1, 1);

            graphicsDevice.ImmediateContext.ComputeShader.Set(computeScanExclusiveShared);
            graphicsDevice.ImmediateContext.ComputeShader.SetConstantBuffer(constantBuffer, 0);
            graphicsDevice.ImmediateContext.ComputeShader.SetUnorderedAccessView(trisCountUAV, 2);
            graphicsDevice.ImmediateContext.ComputeShader.SetUnorderedAccessView(outputUAV, 3);
            graphicsDevice.ImmediateContext.ComputeShader.SetUnorderedAccessView(bufferUAV, 4);

            graphicsDevice.ImmediateContext.Dispatch((int)gridDim.X, (int)gridDim.Y, (int)gridDim.Z);

            graphicsDevice.ImmediateContext.ComputeShader.Set(computeScanExclusiveShared2);

            graphicsDevice.ImmediateContext.Dispatch((int)gridDimShared2.X, (int)gridDimShared2.Y, (int)gridDimShared2.Z);

            graphicsDevice.ImmediateContext.ComputeShader.Set(computeUniformUpdate);

            graphicsDevice.ImmediateContext.Dispatch((int)gridDim.X, (int)gridDim.Y, (int)gridDim.Z);

            buffer.Dispose();
            bufferUAV.Dispose();

            return(outputUAV);
        }