public void Render(IRendererContext context, RenderPasses renderPass, IRenderable renderable) { var c = (VeldridRendererContext)context; var cl = c.CommandList; var sc = c.SceneContext; ITextureManager textureManager = Resolve <ITextureManager>(); IDeviceObjectManager dom = Resolve <IDeviceObjectManager>(); EngineFlags engineFlags = Resolve <IEngineSettings>().Flags; // float depth = gd.IsDepthRangeZeroToOne ? 0 : 1; var sprite = (MultiSprite)renderable; var shaderKey = new SpriteShaderKey(sprite, engineFlags); sprite.PipelineId = shaderKey.GetHashCode(); //if (!shaderKey.UseArrayTexture) // return; cl.PushDebugGroup(sprite.Name); if (sc.PaletteView == null) { return; } TextureView textureView = (TextureView)textureManager?.GetTexture(sprite.Key.Texture); var resourceSet = dom.Get <ResourceSet>((sprite, textureView)); var instanceBuffer = dom.Get <DeviceBuffer>((sprite, sprite)); var uniformInfo = new SpriteUniformInfo { Flags = sprite.Key.Flags, TextureWidth = textureView?.Target.Width ?? 1, TextureHeight = textureView?.Target.Height ?? 1 }; if (sprite.Key.ScissorRegion.HasValue) { IWindowManager wm = Resolve <IWindowManager>(); var screenCoordinates = wm.UiToPixel(sprite.Key.ScissorRegion.Value); cl.SetScissorRect(0, (uint)screenCoordinates.X, (uint)screenCoordinates.Y, (uint)screenCoordinates.Width, (uint)screenCoordinates.Height); } cl.UpdateBuffer(_uniformBuffer, 0, uniformInfo); cl.SetPipeline(_pipelines[shaderKey]); cl.SetGraphicsResourceSet(0, resourceSet); cl.SetGraphicsResourceSet(1, sc.CommonResourceSet); cl.SetVertexBuffer(0, _vertexBuffer); cl.SetIndexBuffer(_indexBuffer, IndexFormat.UInt16); cl.SetVertexBuffer(1, instanceBuffer); //cl.SetViewport(0, new Viewport(0, 0, sc.MainSceneColorTexture.Width, sc.MainSceneColorTexture.Height, depth, depth)); cl.DrawIndexed((uint)Indices.Length, (uint)sprite.ActiveInstances, 0, 0, 0); //cl.SetViewport(0, new Viewport(0, 0, sc.MainSceneColorTexture.Width, sc.MainSceneColorTexture.Height, 0, 1)); if (sprite.Key.ScissorRegion.HasValue) { cl.SetFullScissorRect(0); } cl.PopDebugGroup(); }
public void Render(IRendererContext context, RenderPasses renderPass, IRenderable renderable) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (renderable == null) { throw new ArgumentNullException(nameof(renderable)); } var c = (VeldridRendererContext)context; var cl = c.CommandList; var dom = Resolve <IDeviceObjectManager>(); var engineFlags = Resolve <IEngineSettings>().Flags; var textureManager = Resolve <ITextureManager>(); var sprite = (MultiSprite)renderable; var shaderKey = new SpriteShaderKey(sprite, engineFlags); sprite.PipelineId = shaderKey.GetHashCode(); //if (!shaderKey.UseArrayTexture) // return; cl.PushDebugGroup(sprite.Name); if (c.SceneContext.PaletteView == null) { return; } TextureView textureView = (TextureView)textureManager?.GetTexture(sprite.Key.Texture); var resourceSet = dom.GetDeviceObject <ResourceSet>((sprite, textureView, "ResourceSet")); var instanceBuffer = dom.GetDeviceObject <DeviceBuffer>((sprite, sprite, "InstanceBuffer")); if (sprite.Key.ScissorRegion.HasValue) { IWindowManager wm = Resolve <IWindowManager>(); var screenCoordinates = wm.UiToPixel(sprite.Key.ScissorRegion.Value); cl.SetScissorRect(0, (uint)screenCoordinates.X, (uint)screenCoordinates.Y, (uint)screenCoordinates.Width, (uint)screenCoordinates.Height); } cl.SetPipeline(_pipelines[shaderKey]); cl.SetGraphicsResourceSet(0, resourceSet); cl.SetGraphicsResourceSet(1, c.SceneContext.CommonResourceSet); cl.SetVertexBuffer(0, _vertexBuffer); cl.SetIndexBuffer(_indexBuffer, IndexFormat.UInt16); cl.SetVertexBuffer(1, instanceBuffer); cl.DrawIndexed((uint)Indices.Length, (uint)sprite.ActiveInstances, 0, 0, 0); if (sprite.Key.ScissorRegion.HasValue) { cl.SetFullScissorRect(0); } cl.PopDebugGroup(); }
Pipeline BuildPipeline(GraphicsDevice gd, SceneContext sc, SpriteShaderKey key) { var shaderCache = Resolve <IShaderCache>(); var shaderName = key.UseCylindricalShader ? "CylindricalSprite" : "Sprite"; var vertexShaderName = shaderName + "SV.vert"; var fragmentShaderName = shaderName + "SF.frag"; var vertexShaderContent = shaderCache.GetGlsl(vertexShaderName); var fragmentShaderContent = shaderCache.GetGlsl(fragmentShaderName); if (key.UseArrayTexture) { fragmentShaderName += ".array"; fragmentShaderContent = @"#define USE_ARRAY_TEXTURE " + fragmentShaderContent; } if (key.UsePalette) { fragmentShaderName += ".pal"; fragmentShaderContent = @"#define USE_PALETTE " + fragmentShaderContent; } var shaders = shaderCache.GetShaderPair( gd.ResourceFactory, vertexShaderName, fragmentShaderName, vertexShaderContent, fragmentShaderContent); _shaders.AddRange(shaders); var shaderSet = new ShaderSetDescription(new[] { VertexLayout, InstanceLayout }, shaders); var depthStencilMode = key.PerformDepthTest ? gd.IsDepthRangeZeroToOne ? DepthStencilStateDescription.DepthOnlyLessEqual : DepthStencilStateDescription.DepthOnlyGreaterEqual : DepthStencilStateDescription.Disabled; var rasterizerMode = new RasterizerStateDescription( FaceCullMode.None, PolygonFillMode.Solid, FrontFace.Clockwise, key.PerformDepthTest, // depth test true); // scissor test var pipelineDescription = new GraphicsPipelineDescription( BlendStateDescription.SingleAlphaBlend, depthStencilMode, rasterizerMode, PrimitiveTopology.TriangleList, new ShaderSetDescription(new[] { VertexLayout, InstanceLayout }, shaderSet.Shaders, ShaderHelper.GetSpecializations(gd)), new[] { _perSpriteResourceLayout, sc.CommonResourceLayout }, sc.MainSceneFramebuffer.OutputDescription); var pipeline = gd.ResourceFactory.CreateGraphicsPipeline(ref pipelineDescription); pipeline.Name = $"P_Sprite_{key}"; return(pipeline); }
public IEnumerable <IRenderable> UpdatePerFrameResources(IRendererContext context, IEnumerable <IRenderable> renderables) { var c = (VeldridRendererContext)context; var cl = c.CommandList; var gd = c.GraphicsDevice; var sc = c.SceneContext; ITextureManager textureManager = Resolve <ITextureManager>(); IDeviceObjectManager objectManager = Resolve <IDeviceObjectManager>(); EngineFlags engineFlags = Resolve <IEngineSettings>().Flags; foreach (var renderable in renderables) { var sprite = (MultiSprite)renderable; if (sprite.ActiveInstances == 0) { continue; } var shaderKey = new SpriteShaderKey(sprite, engineFlags); if (!_pipelines.ContainsKey(shaderKey)) { _pipelines.Add(shaderKey, BuildPipeline(gd, sc, shaderKey)); } uint bufferSize = (uint)sprite.Instances.Length * SpriteInstanceData.StructSize; var buffer = objectManager.Get <DeviceBuffer>((sprite, sprite)); if (buffer?.SizeInBytes != bufferSize) { buffer = gd.ResourceFactory.CreateBuffer(new BufferDescription(bufferSize, BufferUsage.VertexBuffer)); buffer.Name = $"B_SpriteInst:{sprite.Name}"; PerfTracker.IncrementFrameCounter("Create InstanceBuffer"); objectManager.Set((sprite, sprite), buffer); } if (sprite.InstancesDirty) { cl.UpdateBuffer(buffer, 0, sprite.Instances); PerfTracker.IncrementFrameCounter("Update InstanceBuffers"); } textureManager?.PrepareTexture(sprite.Key.Texture, context); TextureView textureView = (TextureView)textureManager?.GetTexture(sprite.Key.Texture); var resourceSet = objectManager.Get <ResourceSet>((sprite, textureView)); if (resourceSet == null) { resourceSet = gd.ResourceFactory.CreateResourceSet(new ResourceSetDescription( _perSpriteResourceLayout, gd.PointSampler, textureView, _uniformBuffer)); resourceSet.Name = $"RS_Sprite:{sprite.Key.Texture.Name}"; PerfTracker.IncrementFrameCounter("Create ResourceSet"); objectManager.Set((sprite, textureView), resourceSet); } sprite.InstancesDirty = false; yield return(sprite); } 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 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(); }