Beispiel #1
0
        /// <summary>
        /// Draw the vertices group as primitives, using an optional index buffer (indices) and a <see cref="StreamFrequency"/> object to specify Hardware Instancing information (Shader Model 3 and Windows Only)
        /// </summary>
        /// <param name="state"></param>
        /// <param name="indices">(optional) indices to use during drawing</param>
        /// <param name="primitiveType">Primitive type to draw, eg PrimitiveType.TriangleList</param>
        /// <param name="frequency">(optional) <see cref="StreamFrequency"/> setting the shader model 3 instance frequency data (used for hardware instancing)</param>
        /// <param name="primitveCount">The number of primitives to draw</param>
        /// <param name="startIndex">The start index in the index buffer (defaults to the first index - 0)</param>
        /// <param name="vertexOffset">Starting offset into the vertex buffer (defaults to the first vertex - 0)</param>
        /// <remarks></remarks>
        public void Draw(DrawState state, IIndices indices, PrimitiveType primitiveType, StreamFrequency frequency, int primitveCount, int startIndex, int vertexOffset)
        {
            if (frequency != null && !state.SupportsHardwareInstancing)
            {
                throw new InvalidOperationException("Only windows devices supporting Shader Model 3.0 or better to can use hardware instancing. Check DrawState.SupportsHardwareInstancing");
            }

#if XBOX360
            if (frequency != null)
            {
#if DEBUG
                if (frequency.layout != StreamFrequency.DataLayout.Stream0Geometry_Stream1InstanceData)
                {
                    throw new InvalidOperationException("Only StreamFrequency DataLayout of Stream0Geometry_Stream1InstanceData is emulated on the xbox360");
                }

                if (primitveCount != int.MaxValue ||
                    startIndex != 0 || vertexOffset != 0)
                {
                    throw new ArgumentException("Only default values for primitiveCount, startIndex and vertexOffset may be used when emulating instancing on the xbox");
                }
                if (primitiveType == PrimitiveType.TriangleFan ||
                    primitiveType == PrimitiveType.TriangleStrip ||
                    primitiveType == PrimitiveType.LineStrip)
                {
                    throw new ArgumentException("Only Primitive List Types (eg TriangleList) are supported as a primitiveType when emulating instancing on the xbox");
                }
#endif
                if (indices != null)
                {
                    ((IDeviceIndexBuffer)indices).AllocateForInstancing(state);
                }
            }
#endif

            GraphicsDevice device = state.graphics;

            IDeviceIndexBuffer devib = indices as IDeviceIndexBuffer;
            IndexBuffer        ib    = null;
            if (devib != null)
            {
                ib = devib.GetIndexBuffer(state);
            }

            if (decl == null)
            {
                decl = ((IDeviceVertexBuffer)this).GetVertexDeclaration(state.Application);
            }

            state.VertexDeclaration = decl;

#if DEBUG
            state.ValidateVertexDeclarationForShader(decl, null);
#endif

            int vertices = 0;
            for (int i = 0; i < buffers.Length; i++)
            {
                IDeviceVertexBuffer dev = buffers[i] as IDeviceVertexBuffer;
                if (dev != null)
                {
                    state.SetStream(i, dev.GetVertexBuffer(state), offsets[i], buffers[i].Stride);
                }
                else
                {
                    state.SetStream(i, null, 0, 0);
                }

                if (i == 0)
                {
                    vertices = buffers[i].Count;
                }
                else
                if (frequency == null)
                {
                    vertices = Math.Min(buffers[i].Count, vertices);
                }
            }


            state.IndexBuffer = ib;

            if (ib != null)
            {
                vertices = indices.Count;
            }

            int primitives = 0;
            switch (primitiveType)
            {
            case PrimitiveType.LineList:
                primitives = vertices / 2;
                break;

            case PrimitiveType.LineStrip:
                primitives = vertices - 1;
                break;

            case PrimitiveType.PointList:
                primitives = vertices;
                break;

            case PrimitiveType.TriangleList:
                primitives = vertices / 3;
                break;

            case PrimitiveType.TriangleFan:
            case PrimitiveType.TriangleStrip:
                primitives = vertices - 2;
                break;
            }


            int vertexCount = 0;
            if (indices != null)
            {
                vertexCount = indices.MaxIndex + 1;
            }
            else
            {
                switch (primitiveType)
                {
                case PrimitiveType.LineStrip:
                    vertexCount = primitives * 2;
                    break;

                case PrimitiveType.PointList:
                case PrimitiveType.LineList:
                case PrimitiveType.TriangleList:
                    vertexCount = vertices;
                    break;

                case PrimitiveType.TriangleFan:
                case PrimitiveType.TriangleStrip:
                    vertexCount = primitives * 3;
                    break;
                }
            }

            state.ApplyRenderStateChanges(vertexCount);

#if DEBUG
            int instances = 1;
#endif

#if !XBOX360
            if (frequency != null && frequency.frequency.Length >= this.buffers.Length)
            {
#if DEBUG
                if (frequency.indexFrequency.Length > 0)
                {
                    System.Threading.Interlocked.Increment(ref state.Application.currentFrame.InstancesDrawBatchCount);
                    state.Application.currentFrame.InstancesDrawn += frequency.indexFrequency[0];
                    instances = frequency.indexFrequency[0];
                }
#endif

                for (int i = 0; i < this.buffers.Length; i++)
                {
                    VertexStream vs = device.Vertices[i];
                    if (frequency.frequency[i] != 0)
                    {
                        vs.SetFrequency(frequency.frequency[i]);
                    }
                    if (frequency.indexFrequency[i] != 0)
                    {
                        vs.SetFrequencyOfIndexData(frequency.indexFrequency[i]);
                    }
                    if (frequency.dataFrequency[i] != 0)
                    {
                        vs.SetFrequencyOfInstanceData(frequency.dataFrequency[i]);
                    }
                }
            }
#endif

            if (primitveCount != int.MaxValue)
            {
                if (primitveCount > primitives ||
                    primitveCount <= 0)
                {
                    throw new ArgumentException("primitiveCount");
                }
            }
            else
            {
                primitveCount = primitives;
            }

#if DEBUG
            state.CalcBoundTextures();
#endif

            //it is possible to have the debug runtime throw an exception here when using instancing,
            //as it thinks stream1 doesn't have enough data.
            //This is most common with sprite groups (however sprite groups will use shader-instancing with small groups)
            //eg, drawing a single instance requires only 64bytes in stream1, yet the triangle count could be very large
            //this makes the debug runtime think that stream1 doesn't have enough data
            if (ib != null)
            {
#if DEBUG
                System.Threading.Interlocked.Increment(ref state.Application.currentFrame.DrawIndexedPrimitiveCallCount);
#endif
#if XBOX360
                if (frequency != null)
                {
                    int repeats = frequency.RepeatCount;
#if DEBUG
                    System.Threading.Interlocked.Increment(ref state.Application.currentFrame.InstancesDrawBatchCount);
                    state.Application.currentFrame.InstancesDrawn += frequency.indexFrequency[0];
                    instances = repeats;
#endif
                    int          maxInstances = ((IDeviceIndexBuffer)indices).MaxInstances;
                    int          offset       = 0;
                    VertexBuffer vb           = ((IDeviceVertexBuffer)buffers[1]).GetVertexBuffer(state);

                    while (repeats - offset > 0)
                    {
                        if (offset != 0)
                        {
                            //read the next set of instances
                            state.SetStream(1, vb, offsets[1] + 64 * offset, buffers[1].Stride);
                        }

                        int count = Math.Min(repeats - offset, maxInstances);
                        device.DrawIndexedPrimitives(primitiveType, vertexOffset, indices.MinIndex, ((indices.MaxIndex) + 1) - indices.MinIndex - vertexOffset, startIndex, primitveCount * count);

                        offset += count;
                    }
                }
                else
#endif
                device.DrawIndexedPrimitives(primitiveType, vertexOffset, indices.MinIndex, (indices.MaxIndex - indices.MinIndex) + 1 - vertexOffset, startIndex, primitveCount);
            }
            else
            {
#if DEBUG
                System.Threading.Interlocked.Increment(ref state.Application.currentFrame.DrawPrimitivesCallCount);
#endif
#if XBOX360
                if (frequency != null)
                {
                    int          repeats      = frequency.RepeatCount;
                    int          maxInstances = ((IDeviceIndexBuffer)indices).MaxInstances;
                    int          offset       = 0;
                    VertexBuffer vb           = ((IDeviceVertexBuffer)buffers[1]).GetVertexBuffer(state);

                    while (repeats - offset > 0)
                    {
                        if (offset != 0)
                        {
                            //read the next set of instances
                            state.SetStream(1, vb, offsets[1] + 64 * offset, buffers[1].Stride);
                        }

                        int count = Math.Min(repeats - offset, maxInstances);
                        device.DrawPrimitives(primitiveType, vertexOffset, primitveCount * count);

                        offset += count;
                    }
                }
                else
#endif
                device.DrawPrimitives(primitiveType, vertexOffset, primitveCount);
            }


#if DEBUG
            switch (primitiveType)
            {
            case PrimitiveType.LineList:
            case PrimitiveType.LineStrip:
                state.Application.currentFrame.LinesDrawn += primitives * instances;
                break;

            case PrimitiveType.PointList:
                state.Application.currentFrame.PointsDrawn += primitives * instances;
                break;

            case PrimitiveType.TriangleList:
            case PrimitiveType.TriangleFan:
            case PrimitiveType.TriangleStrip:
                state.Application.currentFrame.TrianglesDrawn += primitives * instances;
                break;
            }
#endif

#if !XBOX360
            if (frequency != null && frequency.frequency.Length >= this.buffers.Length)
            {
                device.Vertices[0].SetFrequency(1);
            }
#endif

            for (int i = 0; i < buffers.Length; i++)
            {
                if (i > 0)
                {
                    state.SetStream(i, null, 0, 0);
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Draw the vertices as primitives with extended parametres, using an optional index buffer (indices)
        /// </summary>
        /// <param name="state"></param>
        /// <param name="indices">indices to use when drawing (may be null)</param>
        /// <param name="primitiveType">Primitive type to use when drawing the buffer</param>
        /// <param name="primitveCount">The number of primitives to draw</param>
        /// <param name="startIndex">The start index in the index buffer (defaults to the first index - 0)</param>
        /// <param name="vertexOffset">Starting offset into the vertex buffer (defaults to the first vertex - 0)</param>
        public void Draw(DrawState state, IIndices indices, PrimitiveType primitiveType, int primitveCount, int startIndex, int vertexOffset)
        {
            GraphicsDevice device = state.graphics;

            if (state.DrawTarget == null)
            {
                throw new InvalidOperationException("Vertices Draw calls should be done within the Draw() call of a DrawTarget object. (otherwise the draw target is undefined)");
            }

            ValidateDisposed();

            IDeviceIndexBuffer devib = (IDeviceIndexBuffer)indices;
            IndexBuffer        ib    = null;

            if (devib != null)
            {
                ib = devib.GetIndexBuffer(state);
            }

            if (decl == null)
            {
                Warm(state);
            }

            VertexBuffer      vb = ((IDeviceVertexBuffer)this).GetVertexBuffer(state);
            VertexDeclaration vd = this.decl;

#if DEBUG
            state.ValidateVertexDeclarationForShader(vd, typeof(VertexType));
#endif

            state.VertexDeclaration = vd;
            state.IndexBuffer       = ib;
            state.SetStream(0, vb, 0, buffer.Stride);

            int vertices = buffer.Count;
            if (indices != null)
            {
                vertices = indices.Count;
            }

            int primitives = 0;
            switch (primitiveType)
            {
            case PrimitiveType.LineList:
                primitives = vertices / 2;
                break;

            case PrimitiveType.LineStrip:
                primitives = vertices - 1;
                break;

            case PrimitiveType.PointList:
                primitives = vertices;
                break;

            case PrimitiveType.TriangleList:
                primitives = vertices / 3;
                break;

            case PrimitiveType.TriangleFan:
            case PrimitiveType.TriangleStrip:
                primitives = vertices - 2;
                break;
            }

            int vertexCount = 0;
            if (indices != null)
            {
                vertexCount = indices.MaxIndex + 1;
            }
            else
            {
                switch (primitiveType)
                {
                case PrimitiveType.LineStrip:
                    vertexCount = primitives * 2;
                    break;

                case PrimitiveType.PointList:
                case PrimitiveType.LineList:
                case PrimitiveType.TriangleList:
                    vertexCount = vertices;
                    break;

                case PrimitiveType.TriangleFan:
                case PrimitiveType.TriangleStrip:
                    vertexCount = primitives * 3;
                    break;
                }
            }

            state.ApplyRenderStateChanges(vertexCount);

            if (primitveCount > primitives ||
                primitveCount <= 0)
            {
                throw new ArgumentException("primitiveCount");
            }

#if DEBUG
            state.CalcBoundTextures();
#endif

            if (indices != null)
            {
#if DEBUG
                System.Threading.Interlocked.Increment(ref state.Application.currentFrame.DrawIndexedPrimitiveCallCount);
#endif

                device.DrawIndexedPrimitives(primitiveType, vertexOffset, indices.MinIndex, (indices.MaxIndex - indices.MinIndex) + 1 - vertexOffset, startIndex, primitveCount);
            }
            else
            {
#if DEBUG
                System.Threading.Interlocked.Increment(ref state.Application.currentFrame.DrawPrimitivesCallCount);
#endif

                device.DrawPrimitives(primitiveType, vertexOffset, primitveCount);
            }



#if DEBUG
            switch (primitiveType)
            {
            case PrimitiveType.LineList:
            case PrimitiveType.LineStrip:
                state.Application.currentFrame.LinesDrawn += primitives;
                break;

            case PrimitiveType.PointList:
                state.Application.currentFrame.PointsDrawn += primitives;
                break;

            case PrimitiveType.TriangleList:
            case PrimitiveType.TriangleFan:
            case PrimitiveType.TriangleStrip:
                state.Application.currentFrame.TrianglesDrawn += primitives;
                break;
            }
#endif
        }
Beispiel #3
0
        public void Draw(DrawState state, IIndices indices, PrimitiveType primitiveType, int primitveCount, int startIndex, int vertexOffset)
        {
            ValidateDisposed();

            IDeviceIndexBuffer devib = (IDeviceIndexBuffer)indices;
            IndexBuffer        ib    = null;

            if (devib != null)
            {
                ib = devib.GetIndexBuffer(state);
            }

            if (_vertexDeclaration == null)
            {
                _vertexDeclaration = Context.VertexDeclarationBuilder.GetDeclaration <TVertexType>();
            }

            VertexBuffer      vb = ((IDeviceVertexBuffer)this).GetVertexBuffer(state);
            VertexDeclaration vd = _vertexDeclaration;

            state.VertexDeclaration = vd;
            state.IndexBuffer       = ib;
            state.SetStream(0, vb, 0, _buffer.Stride);

            int vertices = _buffer.Count;

            if (indices != null)
            {
                vertices = indices.Count;
            }

            int primitives = 0;

            switch (primitiveType)
            {
            case PrimitiveType.LineList:
                primitives = vertices / 2;
                break;

            case PrimitiveType.LineStrip:
                primitives = vertices - 1;
                break;

            case PrimitiveType.PointList:
                primitives = vertices;
                break;

            case PrimitiveType.TriangleList:
                primitives = vertices / 3;
                break;

            case PrimitiveType.TriangleFan:
            case PrimitiveType.TriangleStrip:
                primitives = vertices - 2;
                break;
            }

            int vertexCount = 0;

            if (indices != null)
            {
                vertexCount = indices.MaxIndex + 1;
            }
            else
            {
                switch (primitiveType)
                {
                case PrimitiveType.LineStrip:
                    vertexCount = primitives * 2;
                    break;

                case PrimitiveType.PointList:
                case PrimitiveType.LineList:
                case PrimitiveType.TriangleList:
                    vertexCount = vertices;
                    break;

                case PrimitiveType.TriangleFan:
                case PrimitiveType.TriangleStrip:
                    vertexCount = primitives * 3;
                    break;
                }
            }

            state.ApplyRenderStateChanges(vertexCount);

            if (primitveCount > primitives ||
                primitveCount <= 0)
            {
                throw new ArgumentException("primitiveCount");
            }

            if (indices != null)
            {
                Context.DrawIndexedPrimitive(primitiveType, vertexOffset, indices.MinIndex, (indices.MaxIndex - indices.MinIndex) + 1 - vertexOffset, startIndex, primitveCount);
            }
            else
            {
                Context.DrawPrimitives(primitiveType, vertexOffset, primitveCount);
            }

#if DEBUG
            switch (primitiveType)
            {
            case PrimitiveType.LineList:
            case PrimitiveType.LineStrip:
                Context.PerformanceMonitor.IncreaseCounter(DeviceCounters.LinesDrawn, primitives);
                break;

            case PrimitiveType.PointList:
                Context.PerformanceMonitor.IncreaseCounter(DeviceCounters.PointsDrawn, primitives);
                break;

            case PrimitiveType.TriangleList:
            case PrimitiveType.TriangleFan:
            case PrimitiveType.TriangleStrip:
                Context.PerformanceMonitor.IncreaseCounter(DeviceCounters.TrianglesDrawn, primitives);
                break;
            }
#endif
        }