private void BuildUnsortedVoxelParticlePairs(
        int particleCount,
        TypedComputeBuffer <SpatializerShaderParticlePosition> particlePositionsBuffer,
        float voxelSize)
    {
        SpatializerComputeShader.SetInt("u_particle_count", particleCount);

        SpatializerComputeShader.SetInt("u_voxel_count_per_axis", VoxelsPerAxis);
        SpatializerComputeShader.SetFloat("u_voxel_size", voxelSize);

        SpatializerComputeShader.SetBuffer(
            kernelForBuildUnsortedVoxelParticlePairs,
            "u_particle_positions",
            particlePositionsBuffer);

        SpatializerComputeShader.SetBuffer(
            kernelForBuildUnsortedVoxelParticlePairs,
            "u_out_next_sorted_voxel_particle_pairs",
            voxelParticlePairBuffers.CurrentComputeBuffer);

        SpatializerComputeShader.SetBuffer(
            kernelForBuildUnsortedVoxelParticlePairs,
            "u_out_neighborhoods",
            neighborhoodsBuffer);

        // NOTE: We'll initialize all particles that the sort-algorithm is going to touch.
        // Any exccess/waste particles will be initialized such that they sort to the end of the buffer.
        int sortableParticleCount = CeilingToPowerOfTwo(particleCount);

        ComputeShaderHelpers.DispatchLinearComputeShader(
            SpatializerComputeShader,
            kernelForBuildUnsortedVoxelParticlePairs,
            sortableParticleCount);
    }
    private void BuildForcefieldsBuffer(
        out TypedComputeBuffer <SwarmShaderForcefieldState> outPooledForcefieldsBuffer,
        out int outActiveForcefieldCount)
    {
        // Grab the oldest buffer off the queue, and move it back to mark it as the most recently touched buffer.
        TypedComputeBuffer <SwarmShaderForcefieldState> targetForcefieldsBuffer = forcefieldsBufferQueue.Dequeue();

        forcefieldsBufferQueue.Enqueue(targetForcefieldsBuffer);

        swarmForcefieldCollector.CollectForcefields(
            transform.localToWorldMatrix,
            ref scratchForcefieldStateList);

        if (scratchForcefieldStateList.Count > targetForcefieldsBuffer.count)
        {
            Debug.LogWarningFormat(
                "Discarding some forcefields since [{0}] were wanted, but only [{1}] can be passed to the shader.",
                scratchForcefieldStateList.Count,
                targetForcefieldsBuffer.count);

            scratchForcefieldStateList.RemoveRange(
                targetForcefieldsBuffer.count,
                (scratchForcefieldStateList.Count - targetForcefieldsBuffer.count));
        }

        targetForcefieldsBuffer.SetData(scratchForcefieldStateList.ToArray());

        outPooledForcefieldsBuffer = targetForcefieldsBuffer;
        outActiveForcefieldCount   = scratchForcefieldStateList.Count;
    }
    private void ReleaseBuffers()
    {
        if (scratchParticlePositionsBuffer != null)
        {
            scratchParticlePositionsBuffer.Release();
            scratchParticlePositionsBuffer = null;
        }

        if (neighborhoodsBuffer != null)
        {
            neighborhoodsBuffer.Release();
            neighborhoodsBuffer = null;
        }

        if (spatializationVoxelsBuffer != null)
        {
            spatializationVoxelsBuffer.Release();
            spatializationVoxelsBuffer = null;
        }

        voxelParticlePairBuffers.ReleaseBuffers();

        if (DebugLoggingEnabled)
        {
            Debug.LogFormat("Compute buffers released.");
        }
    }
    private ParticleSpatializer.NeighborhoodResults BuildSwarmerNeighborhoods()
    {
        TypedComputeBuffer <SpatializerShaderParticlePosition> scratchParticlePositionsBuffer =
            particleSpatializer.GetScratchParticlePositionsComputeBuffer(SwarmerCount);

        // Extract the swarmer positions so the spatializer can stay generic.
        {
            CommonSwarmComputeShader.SetInt("u_swarmer_count", SwarmerCount);

            CommonSwarmComputeShader.SetBuffer(
                kernelForExtractSwarmerPositions,
                "u_readable_swarmers",
                swarmerStateBuffers.CurrentComputeBuffer);

            CommonSwarmComputeShader.SetBuffer(
                kernelForExtractSwarmerPositions,
                "u_out_swarmer_positions",
                scratchParticlePositionsBuffer);

            ComputeShaderHelpers.DispatchLinearComputeShader(
                CommonSwarmComputeShader,
                kernelForExtractSwarmerPositions,
                SwarmerCount);
        }

        ParticleSpatializer.NeighborhoodResults result =
            particleSpatializer.BuildNeighborhoodLookupBuffers(
                SwarmerCount,
                scratchParticlePositionsBuffer,
                SwarmerNeighborhoodRadius);

        return(result);
    }
Beispiel #5
0
    public bool TryAllocateComputeBuffersWithGarbage(
        int elementCount)
    {
        bool result = false;

        if (!SystemInfo.supportsComputeShaders)
        {
            Debug.LogError("Compute shaders are not supported on this machine. Is DX11 or later installed?");
        }
        else
        {
            if (CurrentComputeBuffer == null)
            {
                CurrentComputeBuffer = new TypedComputeBuffer <ElementType>(elementCount);
            }

            if (PreviousComputeBuffer == null)
            {
                PreviousComputeBuffer = new TypedComputeBuffer <ElementType>(elementCount);
            }

            if ((CurrentComputeBuffer != null) &&
                (PreviousComputeBuffer != null))
            {
                result = true;
            }
        }

        return(result);
    }
Beispiel #6
0
    private void ReleaseBuffers()
    {
        if (swarmerModelVerticesBuffer != null)
        {
            swarmerModelVerticesBuffer.Release();
            swarmerModelVerticesBuffer = null;

            allocatedModelColorationType = null;
            allocatedModelShapeType      = null;
        }

        if (DebugLoggingEnabled)
        {
            Debug.LogFormat("Compute buffers released.");
        }
    }
    public NeighborhoodResults BuildNeighborhoodLookupBuffers(
        int particleCount,
        TypedComputeBuffer <SpatializerShaderParticlePosition> particlePositionsBuffer,
        float neighborhoodRadius)
    {
        ValidateSufficientParticleCount(particleCount);

        float voxelSize = (2.0f * neighborhoodRadius);

#pragma warning disable 0219 // Warning that variable is assigned but never referenced (these variables are for inspection in the debugger).
        SpatializerShaderParticlePosition[]         debugParticlePositions             = null;
        SpatializerShaderVoxelParticlePair[]        debugUnsortedParticlePairs         = null;
        SpatializerShaderNeighborhood[]             debugNeighborhoods                 = null;
        List <SpatializerShaderVoxelParticlePair[]> debugVoxelParticlePairsPerSortStep = null;
        SpatializerShaderVoxelParticlePair[]        debugSortedParticlePairs           = null;
        SpatializerShaderSpatializationVoxel[]      debugSpatializationVoxels          = null;
#pragma warning restore 0219

        if (DebugCaptureSingleFrame)
        {
            debugParticlePositions = particlePositionsBuffer.DebugGetDataBlocking();
        }

        BuildUnsortedVoxelParticlePairs(
            particleCount,
            particlePositionsBuffer,
            voxelSize);

        if (DebugCaptureSingleFrame)
        {
            debugUnsortedParticlePairs = voxelParticlePairBuffers.CurrentComputeBuffer.DebugGetDataBlocking();
            debugNeighborhoods         = neighborhoodsBuffer.DebugGetDataBlocking();
        }

        SortVoxelParticlePairs(
            particleCount,
            out debugVoxelParticlePairsPerSortStep);

        if (DebugCaptureSingleFrame)
        {
            debugSortedParticlePairs = voxelParticlePairBuffers.CurrentComputeBuffer.DebugGetDataBlocking();
        }

        BuildSpatializationVoxels(particleCount);

        if (DebugCaptureSingleFrame)
        {
            debugSpatializationVoxels = spatializationVoxelsBuffer.DebugGetDataBlocking();
        }

        // TODO: Export: particle indices, neighborhoods

        if (DebugCaptureSingleFrame)
        {
            DebugCaptureSingleFrame = false;

#pragma warning disable 0168 // Warning that variable is assigned but never referenced (these variables are for inspection in the debugger).
            var allPerParticleValues =
                DebugParticleBufferCombinedEnumeration.ZipParticleBuffers(
                    debugParticlePositions,
                    debugUnsortedParticlePairs,
                    debugNeighborhoods).ToArray();

            var sortStepsDebug = DebugSortStepKeys(debugVoxelParticlePairsPerSortStep).ToArray();
#pragma warning restore 0168

            Debug.Assert(DebugSortedVoxelParticlePairsAreValid(
                             particleCount,
                             debugSortedParticlePairs));

            Debug.Assert(DebugSpatializationVoxelsAreValid(
                             particleCount,
                             debugSortedParticlePairs,
                             TotalVoxelCount,
                             debugSpatializationVoxels));

            Debug.LogWarning("Finished debug-dumping the compute buffers. Surprised? Attach the unity debugger and breakpoint this line.");
        }

        var result = new NeighborhoodResults()
        {
            VoxelParticlePairsBuffer   = voxelParticlePairBuffers.CurrentComputeBuffer,
            SpatializationVoxelsBuffer = spatializationVoxelsBuffer,
            NeighborhoodsBuffer        = neighborhoodsBuffer,
        };

        return(result);
    }
    private bool TryAllocateBuffers()
    {
        bool result = false;

        if (!SystemInfo.supportsComputeShaders)
        {
            Debug.LogError("Compute shaders are not supported on this machine. Is DX11 or later installed?");
        }
        else if (MaxParticleCount <= 0)
        {
            if (DebugLoggingEnabled)
            {
                Debug.LogFormat("Buffer-allocation silently aborted because we haven't yet been given a maximum particle count.");
            }
        }
        else if (SpatializerComputeShader != null)
        {
            kernelForBuildUnsortedVoxelParticlePairs =
                SpatializerComputeShader.FindKernel("kernel_build_unsorted_voxel_particle_pairs");

            kernelForAdvanceSortOfVoxelParticlePairs =
                SpatializerComputeShader.FindKernel("kernel_advance_sort_of_voxel_particle_pairs");

            kernelForBuildSpatializationVoxels =
                SpatializerComputeShader.FindKernel("kernel_build_spatialization_voxels");

            if (scratchParticlePositionsBuffer == null)
            {
                scratchParticlePositionsBuffer =
                    new TypedComputeBuffer <SpatializerShaderParticlePosition>(MaxParticleCount);
            }

            if (neighborhoodsBuffer == null)
            {
                neighborhoodsBuffer =
                    new TypedComputeBuffer <SpatializerShaderNeighborhood>(MaxParticleCount);
            }

            if (spatializationVoxelsBuffer == null)
            {
                spatializationVoxelsBuffer =
                    new TypedComputeBuffer <SpatializerShaderSpatializationVoxel>(TotalVoxelCount);
            }

            voxelParticlePairBuffers.TryAllocateComputeBuffersWithGarbage(MaxParticleCount);

            if (IsInitialized)
            {
                result = true;
            }
            else
            {
                // Abort any partial-allocations.
                ReleaseBuffers();
            }
        }

        if (DebugLoggingEnabled)
        {
            Debug.LogFormat("Compute buffer allocation attempted. [Success={0}]", result);
        }

        return(result);
    }
Beispiel #9
0
    private bool TryAllocateBuffers()
    {
        bool result = false;

        if (!SystemInfo.supportsComputeShaders)
        {
            Debug.LogError("Compute shaders are not supported on this machine. Is DX11 or later installed?");
        }
        else
        {
            if (swarmerModelVerticesBuffer == null)
            {
                var swarmerModelVertices = new List <SwarmShaderSwarmerModelVertex>();

                switch (ModelShape)
                {
                case ModelShapeType.SimpleFlatTriangle:
                {
                    AppendFlatDoubleSidedTriangleVerticesToModel(
                        0.0f,                                 // leftSegmentFraction
                        0.0f,                                 // rightSegmentFraction
                        ModelColoration,
                        Matrix4x4.identity,
                        ref swarmerModelVertices);

                    break;
                }

                case ModelShapeType.TriamondWing:
                {
                    AppendTriangularBifrustumVerticesToModel(
                        0.0f,                                 // leftSegmentFraction
                        0.0f,                                 // rightSegmentFraction
                        ModelColoration,
                        FacetType.Generic,                    // Front-left (before rotation).
                        FacetType.Generic,                    // Front-right (before rotation).
                        FacetType.Front,                      // Rear (before rotation).
                        Matrix4x4.TRS(
                            new Vector3(
                                0.0f,
                                0.0f,
                                (1.0f - Mathf.Sin(30.0f * Mathf.Deg2Rad))),
                            Quaternion.AngleAxis(180, Vector3.up),
                            Vector3.one),
                        ref swarmerModelVertices);

                    AppendTriangularBifrustumVerticesToModel(
                        0.0f,                                 // leftSegmentFraction
                        1.0f,                                 // rightSegmentFraction
                        ModelColoration,
                        FacetType.Generic,                    // Front-left (before rotation).
                        FacetType.Front,                      // Front-right (before rotation).
                        FacetType.Rear,                       // Rear (before rotation).
                        Matrix4x4.TRS(
                            new Vector3(
                                (1.0f * Mathf.Cos(30.0f * Mathf.Deg2Rad)),
                                0.0f,
                                0.0f),
                            Quaternion.identity,
                            Vector3.one),
                        ref swarmerModelVertices);

                    AppendTriangularBifrustumVerticesToModel(
                        1.0f,                                 // leftSegmentFraction
                        0.0f,                                 // rightSegmentFraction
                        ModelColoration,
                        FacetType.Front,                      // Front-left (before rotation).
                        FacetType.Generic,                    // Front-right (before rotation).
                        FacetType.Rear,                       // Rear (before rotation).
                        Matrix4x4.TRS(
                            new Vector3(
                                (-1.0f * Mathf.Cos(30.0f * Mathf.Deg2Rad)),
                                0.0f,
                                0.0f),
                            Quaternion.identity,
                            Vector3.one),
                        ref swarmerModelVertices);

                    break;
                }

                default:
                    throw new System.ComponentModel.InvalidEnumArgumentException();
                }

                swarmerModelVerticesBuffer =
                    new TypedComputeBuffer <SwarmShaderSwarmerModelVertex>(swarmerModelVertices.Count);

                swarmerModelVerticesBuffer.SetData(swarmerModelVertices.ToArray());

                allocatedModelColorationType = ModelColoration;
                allocatedModelShapeType      = ModelShape;
            }

            if (swarmerModelVerticesBuffer != null)
            {
                result = true;
            }
            else
            {
                // Abort any partial-allocations.
                ReleaseBuffers();
            }
        }

        if (DebugLoggingEnabled)
        {
            Debug.LogFormat("Compute buffer allocation attempted. [Success={0}]", result);
        }

        return(result);
    }