Пример #1
0
 internal static void ArrayViewGetVariableViewKernel(
     Index1 index,
     ArrayView <int> data,
     ArrayView <int> source)
 {
     data[index] = source.GetVariableView(index).Value;
 }
Пример #2
0
 /// <summary>
 /// A simple 1D kernel using a pre-defined implementation
 /// of atomic add for doubles.
 /// <param name="index">The current thread index.</param>
 /// <param name="dataView">The view pointing to our memory buffer.</param>
 /// <param name="value">The value to add.</param>
 static void AddDoubleBuiltInKernel(
     Index index,
     ArrayView <double> dataView,
     double value)
 {
     // atomic add: dataView[0] += value;
     Atomic.Add(dataView.GetVariableView(0), value);
 }
Пример #3
0
        /// <summary>
        /// A simple 1D kernel using basic atomic functions.
        /// The second parameter (<paramref name="dataView"/>) represents the target
        /// view for all atomic operations.
        /// </summary>
        /// <param name="index">The current thread index.</param>
        /// <param name="dataView">The view pointing to our memory buffer.</param>
        /// <param name="constant">A uniform constant.</param>
        static void AtomicOperationKernel(
            Index index,               // The global thread index (1D in this case)
            ArrayView <int> dataView,  // A view to a chunk of memory (1D in this case)
            int constant)              // A sample uniform constant
        {
            // dataView[0] += constant
            Atomic.Add(dataView.GetVariableView(0), constant);

            // dataView[1] -= constant
            Atomic.Sub(dataView.GetVariableView(1), constant);

            // dataView[2] = Max(dataView[2], constant)
            Atomic.Max(dataView.GetVariableView(2), constant);

            // dataView[3] = Min(dataView[3], constant)
            Atomic.Min(dataView.GetVariableView(3), constant);

            // dataView[4] = Min(dataView[4], constant)
            Atomic.And(dataView.GetVariableView(4), constant);

            // dataView[5] = Min(dataView[5], constant)
            Atomic.Or(dataView.GetVariableView(5), constant);

            // dataView[6] = Min(dataView[6], constant)
            Atomic.Xor(dataView.GetVariableView(6), constant);
        }
Пример #4
0
        internal static void Vector4dAddKernel(
            Index1 index,
            ArrayView <Vector4> input,
            Vector4 operand)
        {
            var target = input.GetVariableView(index);

            target.AtomicAdd(operand);
        }
Пример #5
0
        internal static void ArrayViewGetSubVariableViewKernel(
            Index1 index,
            ArrayView <int> data,
            ArrayView <Pair <int> > source)
        {
            var variableView = source.GetVariableView(index);
            var actualView   = variableView.GetSubView <int>(sizeof(int));

            data[index] = actualView.Value;
        }
Пример #6
0
        static void VariableViewAccess(ArrayView <int> view)
        {
            // Creates a variable view that points to the last accessible element
            // of the provided view
            var variableView = view.GetVariableView(view.Length - 1);

            variableView.Value = 13;

            Debug.Assert(variableView.Value == view[view.Length - 1]);
        }
Пример #7
0
        internal static void VariableSubViewKernel(
            Index1 index,
            ArrayView <int> data,
            ArrayView <int> data2,
            ArrayView <long> source)
        {
            var view = source.GetVariableView(index);

            data[index]  = view.GetSubView <int>(0).Value;
            data2[index] = view.GetSubView <int>(sizeof(int)).Value;
        }
 /// <summary cref="IReductionFinalizer{T, TReduction}.Finalize(GroupedIndex, ArrayView{T}, T, TReduction)"/>
 public void Finalize(
     GroupedIndex index,
     ArrayView <T> output,
     T reducedValue,
     TReduction reduction)
 {
     if (index.GroupIdx.IsFirst)
     {
         reduction.AtomicReduce(output.GetVariableView(), reducedValue);
     }
 }
Пример #9
0
        static void VariableViewAccess(ArrayView <int> view)
        {
            // Creates a variable view that points to the last accessible element
            // of the provided view
            var variableView = view.GetVariableView(view.Length - 1);

            variableView.Store(13);

            // Note that view.Load(idx) is an alias for view[idx]
            Debug.Assert(variableView.Load() == view.Load(view.Length - 1));
        }
Пример #10
0
 /// <summary>
 /// A simple 1D kernel using a custom atomic implementation
 /// of Atomic.Add(ArrayView<double>, double) that leverages pre-defined
 /// compare-exchange functionality for doubles.
 /// <param name="index">The current thread index.</param>
 /// <param name="dataView">The view pointing to our memory buffer.</param>
 /// <param name="value">The value to add.</param>
 static void AddDoubleAtomicILGPUFunctionsKernel(
     Index index,
     ArrayView <double> dataView,
     double value)
 {
     // atomic add: dataView[0] += value;
     Atomic.MakeAtomic(
         dataView.GetVariableView(0),
         value,
         new AddDoubleOperation(),
         new CompareExchangeDouble());
 }
Пример #11
0
        static void UnsafeVariableViewAccess(ArrayView <int> view)
        {
            // Creates a variable view that points to the first element
            var variableView = view.GetVariableView(0);

            // Cast variable view to an accessible sub element in range.
            // The passed offset is the relative offset of the sub view in bytes.
            // The primary use case for this functionality are direct accesses
            // to structure members.
            var subView = variableView.GetSubView <short>(sizeof(short));

            subView.Value = short.MaxValue;

            Debug.Assert(variableView.Value == short.MaxValue << 16);
        }
Пример #12
0
        /// <summary>
        /// A simple kernel that uses a variable-sub-view access to compute
        /// the target memory location for an atomic operation.
        /// </summary>
        /// <param name="index">The thread index.</param>
        /// <param name="elements">The elements to check.</param>
        /// <param name="view">The target view.</param>
        /// <param name="comparisonValue">The comparison value to use.</param>
        static void MyKernel(
            Index1 index,
            ArrayView <int> elements,
            ArrayView <ComposedStructure> view,
            int comparisonValue)
        {
            var element = elements[index];

            if (element == comparisonValue)
            {
                var baseView    = view.GetVariableView(0);
                var counterView = baseView.GetSubView <int>(ComposedStructure.ElementCounterOffset);
                Atomic.Add(ref counterView.Value, 1);
            }
        }
Пример #13
0
        static void Test3Kernel(
            GroupedIndex index,
            ArrayView<short> heights,
            ArrayView<float> matrices,
            ArrayView<float> horizon,
            int a_line,
            int a_sample,

            [SharedMemory(1440)]
            ArrayView<float> horizon_shared)
        {
            var idx = index.GroupIdx;
            const int patch_size = 128;

            // Do the calculation
            var aline = index.GridIdx;
            for (var asample = 0; asample < patch_size; asample++)
            {
                // Copy horizon for a[line,sample] into shared memory
                {
                    var dim = Group.Dimension.X;
                    var len = horizon_shared.Length;
                    var passes = (len + (dim - 1)) / dim;
                    var offset = (aline * patch_size + asample) * len;
                    for (var pass = 0; pass < passes; pass++)
                    {
                        var ptr = pass * dim + idx;
                        if (ptr < len)
                            horizon_shared[ptr] = horizon[ptr + offset];
                        // Note warp divergence
                    }
                }

                Group.Barrier();

                // Copy the matrix into registers
                var pos = (aline * patch_size + asample) * 12;

                var row0x = matrices[pos++];
                var row1x = matrices[pos++];
                var row2x = matrices[pos++];
                var row3x = matrices[pos++];

                var row0y = matrices[pos++];
                var row1y = matrices[pos++];
                var row2y = matrices[pos++];
                var row3y = matrices[pos++];

                var row0z = matrices[pos++];
                var row1z = matrices[pos++];
                var row2z = matrices[pos++];
                var row3z = matrices[pos];

                for (var oline = 0; oline < patch_size; oline++)
                {
                    // osample = idx
                    var relz = 0.5d * heights[aline * patch_size + idx];
                    var radius = MoonRadius + relz / 1000d;
                    var line = a_line + aline;
                    var sample = a_sample + idx;

                    var map_x = (sample - S0) * Scale;
                    var map_y = (L0 - line) * Scale;
                    var P = Math.Sqrt(map_x * map_x + map_y * map_y);
                    var C = 2d * Math.Atan2(P, 2 * MoonRadius);
                    var latitude = Math.Asin(Math.Cos(C) * Math.Sin(LatP) + map_y * Math.Sin(C) * Math.Cos(LatP) / P);
                    var longitude = LonP + Math.Atan2(map_x, map_y * LonFactor);

                    var latdeg = latitude * 180d / Math.PI;
                    var londeg = longitude * 180d / Math.PI;

                    // Calculate the other point in ME frame
                    var z_me = radius * Math.Sin(latitude);
                    var c = radius * Math.Cos(latitude);
                    var x_me = c * Math.Cos(longitude);
                    var y_me = c * Math.Sin(longitude);

                    // Transform the point to the local frame
                    var x = x_me * row0x + y_me * row1x + z_me * row2x + row3x;
                    var y = x_me * row0y + y_me * row1y + z_me * row2y + row3y;
                    var z = x_me * row0z + y_me * row1z + z_me * row2z + row3z;

                    //                        if (idx == 0)
                    //                            relz = relz;

                    var azimuth = Math.Atan2(y, x) + Math.PI;  // [0,2 PI]
                    var alen = Math.Sqrt(x * x + y * y);
                    var slope = z / alen;
                    var slopef = (float)slope;

                    var horizon_index = (int)(0.5d + 1439 * (azimuth / (2d * Math.PI)));
                    Atomic.Max(horizon_shared.GetVariableView(horizon_index), slopef);
                    //horizon_shared[horizon_index] = 1f;
                }

                Group.Barrier();

                {
                    var dim = Group.Dimension.X;
                    var len = horizon_shared.Length;
                    var passes = (len + (dim - 1)) / dim;
                    var offset = (aline * patch_size + asample) * len;
                    for (var pass = 0; pass < passes; pass++)
                    {
                        var ptr = pass * dim + idx;
                        if (ptr < len)
                            horizon[ptr + offset] = horizon_shared[ptr];
                        // Note warp divergence
                    }
                }
            }
        }
Пример #14
0
        static void ShadowKernel1(
            GroupedIndex2 index,
            ArrayView <float> points,
            ArrayView <float> matrices,
            ArrayView <int> horizon,
            ArrayView <float> test_array,

            [SharedMemory(1440)]
            ArrayView <int> horizon_shared)
        {
            var target_line   = index.GridIdx.Y;
            var target_sample = index.GridIdx.X;
            var caster_line   = index.GroupIdx.Y;

            Debug.Assert(index.GroupIdx.X == 1);

            // Copy horizon for a[target_line,target_sample] into shared memory
            {
                var dim    = Group.Dimension.Y;
                var len    = horizon_shared.Length;
                var passes = (len + (dim - 1)) / dim;
                var offset = (target_line * TerrainPatch.DefaultSize + target_sample) * len;
                for (var pass = 0; pass < passes; pass++)
                {
                    var ptr = pass * dim + caster_line;
                    if (ptr < len)  // divergence
                    {
                        horizon_shared[ptr] = horizon[ptr + offset];
                    }
                }
            }

            Group.Barrier();

            // Copy the matrix into registers
            var pos = (target_line * TerrainPatch.DefaultSize + target_sample) * 12;

            var row0x = matrices[pos++];
            var row1x = matrices[pos++];
            var row2x = matrices[pos++];
            var row3x = matrices[pos++];

            var row0y = matrices[pos++];
            var row1y = matrices[pos++];
            var row2y = matrices[pos++];
            var row3y = matrices[pos++];

            var row0z = matrices[pos++];
            var row1z = matrices[pos++];
            var row2z = matrices[pos++];
            var row3z = matrices[pos];

            for (var caster_sample = 0; caster_sample < TerrainPatch.DefaultSize; caster_sample++)
            {
                // Fetch the other point in local frame
                var points_offset = (caster_line * TerrainPatch.DefaultSize + caster_sample) * 3;
                var x_patch       = points[points_offset];
                var y_patch       = points[points_offset + 1];
                var z_patch       = points[points_offset + 2];

                // Transform the point to the local frame
                var x = x_patch * row0x + y_patch * row1x + z_patch * row2x + row3x;
                var y = x_patch * row0y + y_patch * row1y + z_patch * row2y + row3y;
                var z = x_patch * row0z + y_patch * row1z + z_patch * row2z + row3z;

                // Adjust for solar array height (this is temporary, and I'm not sure we want this in the final version)
                z -= ObserverHeight;                            // meters

                var azimuth = GPUMath.Atan2(y, x) + GPUMath.PI; // [0,2 PI]
                var alen    = GPUMath.Sqrt(x * x + y * y);
                var slope   = z / alen;

                var slopem = slope > 2f ? 2f : slope;
                slopem = slopem < -2f ? -2f : slopem;
                slopem = slopem / 4f;

                var slopei = (int)(slopem * 1000000);

                var horizon_index = (int)(0.5f + 1439 * (azimuth / (2f * GPUMath.PI)));
                Atomic.Max(horizon_shared.GetVariableView(horizon_index), slopei);

                if (caster_sample == 0 && caster_line == 0 && target_line == 0 && target_sample == 0)
                {
                    test_array[0]  = x_patch;
                    test_array[1]  = y_patch;
                    test_array[2]  = z_patch;
                    test_array[3]  = x;
                    test_array[4]  = y;
                    test_array[5]  = z;
                    test_array[6]  = slope;
                    test_array[7]  = slopem;
                    test_array[8]  = slopei;
                    test_array[9]  = row3x;
                    test_array[10] = row3y;
                    test_array[11] = row3z;
                }
            }

            Group.Barrier();

            {
                var dim    = Group.Dimension.Y;
                var len    = horizon_shared.Length;
                var passes = (len + (dim - 1)) / dim;
                var offset = (target_line * TerrainPatch.DefaultSize + target_sample) * len;
                for (var pass = 0; pass < passes; pass++)
                {
                    var ptr = pass * dim + caster_line;
                    if (ptr < len)  // divergence
                    {
                        horizon[ptr + offset] = horizon_shared[ptr];
                    }
                }
            }
        }