Beispiel #1
0
        public void UpdatePerFrameResources(IRendererContext context, IEnumerable <IRenderable> renderables, IList <IRenderable> results)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (renderables == null)
            {
                throw new ArgumentNullException(nameof(renderables));
            }
            if (results == null)
            {
                throw new ArgumentNullException(nameof(results));
            }

            var c              = (VeldridRendererContext)context;
            var cl             = c.CommandList;
            var gd             = c.GraphicsDevice;
            var textureManager = Resolve <ITextureManager>();
            var objectManager  = Resolve <IDeviceObjectManager>();
            var engineFlags    = Resolve <IEngineSettings>().Flags;

            foreach (var renderable in renderables)
            {
                var sprite = (MultiSprite)renderable;
                if (sprite.ActiveInstances == 0)
                {
                    continue;
                }

                cl.PushDebugGroup(sprite.Name);
                var shaderKey = new SpriteShaderKey(sprite, engineFlags);
                if (!_pipelines.ContainsKey(shaderKey))
                {
                    _pipelines.Add(shaderKey, BuildPipeline(gd, c.SceneContext, shaderKey));
                }

                uint bufferSize = (uint)sprite.Instances.Length * SpriteInstanceData.StructSize;
                var  buffer     = objectManager.GetDeviceObject <DeviceBuffer>((sprite, sprite, "InstanceBuffer"));
                if (buffer?.SizeInBytes != bufferSize)
                {
                    buffer      = gd.ResourceFactory.CreateBuffer(new BufferDescription(bufferSize, BufferUsage.VertexBuffer));
                    buffer.Name = $"B_Inst:{sprite.Name}";
                    PerfTracker.IncrementFrameCounter("Create InstanceBuffer");
                    objectManager.SetDeviceObject((sprite, sprite, "InstanceBuffer"), buffer);
                    sprite.InstancesDirty = true;
                }

                if (sprite.InstancesDirty)
                {
                    var instances = sprite.Instances;
                    VeldridUtil.UpdateBufferSpan(cl, buffer, instances);
                    PerfTracker.IncrementFrameCounter("Update InstanceBuffers");
                }

                textureManager?.PrepareTexture(sprite.Key.Texture, context);
                TextureView textureView = (TextureView)textureManager?.GetTexture(sprite.Key.Texture);

                var uniformBuffer = objectManager.GetDeviceObject <DeviceBuffer>((sprite, textureView, "UniformBuffer"));
                if (uniformBuffer == null)
                {
                    uniformBuffer      = gd.ResourceFactory.CreateBuffer(new BufferDescription((uint)Unsafe.SizeOf <SpriteUniformInfo>(), BufferUsage.UniformBuffer));
                    uniformBuffer.Name = $"B_SpriteUniform:{sprite.Name}";
                    PerfTracker.IncrementFrameCounter("Create sprite uniform buffer");
                    objectManager.SetDeviceObject((sprite, textureView, "UniformBuffer"), uniformBuffer);

                    var uniformInfo = new SpriteUniformInfo
                    {
                        Flags         = sprite.Key.Flags,
                        TextureWidth  = textureView?.Target.Width ?? 1,
                        TextureHeight = textureView?.Target.Height ?? 1
                    };
                    cl.UpdateBuffer(uniformBuffer, 0, uniformInfo);
                }

                var resourceSet = objectManager.GetDeviceObject <ResourceSet>((sprite, textureView, "ResourceSet"));
                if (resourceSet == null)
                {
                    resourceSet = gd.ResourceFactory.CreateResourceSet(new ResourceSetDescription(
                                                                           _perSpriteResourceLayout,
                                                                           textureView,
                                                                           gd.PointSampler,
                                                                           uniformBuffer));
                    resourceSet.Name = $"RS_Sprite:{sprite.Key.Texture.Name}";
                    PerfTracker.IncrementFrameCounter("Create ResourceSet");
                    objectManager.SetDeviceObject((sprite, textureView, "ResourceSet"), resourceSet);
                }

                sprite.InstancesDirty = false;
                results.Add(sprite);
                cl.PopDebugGroup();
            }

            Resolve <ISpriteManager>().Cleanup();
        }
        public void UpdatePerFrameResources(IRendererContext context, IEnumerable <IRenderable> renderables, IList <IRenderable> results)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (renderables == null)
            {
                throw new ArgumentNullException(nameof(renderables));
            }
            if (results == null)
            {
                throw new ArgumentNullException(nameof(results));
            }

            var c             = (VeldridRendererContext)context;
            var cl            = c.CommandList;
            var gd            = c.GraphicsDevice;
            var objectManager = Resolve <IDeviceObjectManager>();

            foreach (var renderable in renderables)
            {
                var overlay = (InfoOverlay)renderable;
                // Only render if an overlay is being shown
                if (overlay.ExamineOpacity + overlay.ManipulateOpacity + overlay.TalkOpacity + overlay.TakeOpacity <= 0)
                {
                    continue;
                }

                cl.PushDebugGroup("Info Overlay");
                var tiles  = overlay.Tiles;
                var buffer = objectManager.GetDeviceObject <DeviceBuffer>((overlay, overlay, "Tiles"));
                if (buffer?.SizeInBytes != tiles.Length)
                {
                    var size = 16 * (((uint)tiles.Length + 15) / 16);
                    buffer      = gd.ResourceFactory.CreateBuffer(new BufferDescription(size, BufferUsage.StructuredBufferReadOnly, 4));
                    buffer.Name = "B_InfoOverlayTiles";
                    objectManager.SetDeviceObject((overlay, overlay, "Tiles"), buffer);
                    overlay.BufferDirty = true;
                }

                if (overlay.BufferDirty)
                {
                    VeldridUtil.UpdateBufferSpan(cl, buffer, tiles);
                    PerfTracker.IncrementFrameCounter("Update InstanceBuffers");
                }

                var uniformBuffer = objectManager.GetDeviceObject <DeviceBuffer>((overlay, overlay, "UniformBuffer"));
                if (uniformBuffer == null)
                {
                    uniformBuffer = gd.ResourceFactory.CreateBuffer(new BufferDescription(
                                                                        (uint)Unsafe.SizeOf <InfoOverlayUniforms>(), BufferUsage.UniformBuffer));
                    uniformBuffer.Name = "InfoOverlayUniformBuffer";
                    PerfTracker.IncrementFrameCounter("Create info overlay uniform buffer");
                    objectManager.SetDeviceObject((overlay, overlay, "UniformBuffer"), uniformBuffer);
                }

                var uniformInfo = new InfoOverlayUniforms
                {
                    Examine    = overlay.ExamineOpacity,
                    Manipulate = overlay.ManipulateOpacity,
                    Talk       = overlay.TalkOpacity,
                    Take       = overlay.TakeOpacity,
                    Width      = overlay.Width,
                    Height     = overlay.Height,
                    TileWidth  = overlay.TileWidth,
                    TileHeight = overlay.TileHeight,
                };
                cl.UpdateBuffer(uniformBuffer, 0, uniformInfo);

                var resourceSet = objectManager.GetDeviceObject <ResourceSet>((overlay, overlay, "ResourceSet"));
                if (resourceSet == null)
                {
                    resourceSet = gd.ResourceFactory.CreateResourceSet(new ResourceSetDescription(
                                                                           _perSpriteResourceLayout,
                                                                           buffer,
                                                                           uniformBuffer));
                    resourceSet.Name = "RS_InfoOverlay";
                    PerfTracker.IncrementFrameCounter("Create ResourceSet");
                    objectManager.SetDeviceObject((overlay, overlay, "ResourceSet"), resourceSet);
                }

                results.Add(overlay);
                overlay.BufferDirty = false;
                cl.PopDebugGroup();
            }
        }