private void RecreateAnimations() { unsafe { var nonEmpty = InstanceLists.Where(e => e.Value.Count > 0); var ptr = (byte *)AnimationUniform.Map(0, nonEmpty.Count() * Animation.MaxInstructions); foreach (var keyList in nonEmpty) { if (!keyList.Value.Updated) { ptr += Animation.SizeStd140; continue; } var(texture, animation) = ((Texture2D, Animation))keyList.Key; if (animation is null) { Animation.WriteNullToBuffer(ptr, out ptr); } else { animation.WriteToBuffer(ptr, out ptr); } } AnimationUniform.Unmap(); } }
private InstanceList GetInstanceList(object listChoosingInfo) { if (InstanceLists.TryGetValue(listChoosingInfo, out var list)) { return(list); } var newList = new InstanceList(this); InstanceLists.Add(listChoosingInfo, newList); return(newList); }
private void RecreateInstanceBuffers() { // Create sets var listInd = 0; foreach (var keyList in InstanceLists.Where(e => e.Value.Count > 0)) { var list = keyList.Value; VKBuffer <SpriteInstanceInfo> computeBuffer; if (!ComputeInstanceBuffers.TryGetValue(list, out computeBuffer)) { computeBuffer = VKBuffer <SpriteInstanceInfo> .StorageBuffer( $"{nameof(SpriteEffect)} compute instance buffer for list {list}", Graphics, MaxSprites ); ComputeInstanceBuffers.Add(list, computeBuffer); } VKBuffer <VertexInstance> vertexBuffer; if (!VertexInstanceBuffers.TryGetValue(list, out vertexBuffer)) { vertexBuffer = VKBuffer <VertexInstance> .StorageBuffer( $"{nameof(SpriteEffect)} vertex instance buffer for list {list}", Graphics, MaxSprites ); VertexInstanceBuffers.Add(list, vertexBuffer); } using (var stagingBuffer = VKBuffer <SpriteInstanceInfo> .StagingBuffer( $"{nameof(SpriteEffect)}.{nameof(RecreateInstanceBuffers)} staging buffer", Graphics, list.Count )) { unsafe { var ptr = stagingBuffer.Map(0, list.Count); if (list.Updated) { var i = 0; foreach (SpriteInstance inst in list.AllInstances) { if (i > MaxSprites) { throw new InvalidOperationException("Too many similar sprites; raise the sprite limit on the effect"); } *ptr = new SpriteInstanceInfo { Time = 0f, Position = inst.StoredPosition, Velocity = inst.StoredVelocity, Scale = inst.StoredScale, Rotation = inst.StoredRotation, ListIndex = listInd, Rectangle = inst.Rectangle, AnimationTime = inst.AnimationTime }; ptr++; i++; } } else { foreach (SpriteInstance inst in list.AllInstances) { (*ptr).ListIndex = listInd; ptr++; } } stagingBuffer.Unmap(); } using (var stagingFence = Graphics.Device.CreateFence(new FenceCreateInfo())) { using (var stagingCommands = Graphics.TransferQueueFamily.CreateCommandBuffers(CommandBufferLevel.Primary, 1)[0]) { stagingCommands.Begin(); stagingCommands.CmdPipelineBarrier( PipelineStages.TopOfPipe, PipelineStages.Transfer, bufferMemoryBarriers: new BufferMemoryBarrier[] { new BufferMemoryBarrier( computeBuffer.Buffer, Accesses.None, Accesses.TransferWrite, 0L, stagingBuffer.Size ) } ); stagingCommands.CmdCopyBuffer( stagingBuffer.Buffer, computeBuffer.Buffer, new BufferCopy[] { new BufferCopy(stagingBuffer.Size) } ); stagingCommands.CmdPipelineBarrier( PipelineStages.Transfer, PipelineStages.ComputeShader, bufferMemoryBarriers: new BufferMemoryBarrier[] { new BufferMemoryBarrier( computeBuffer.Buffer, Accesses.TransferWrite, Accesses.ShaderRead, 0L, stagingBuffer.Size ) } ); stagingCommands.CmdPipelineBarrier( PipelineStages.Transfer, PipelineStages.VertexInput, bufferMemoryBarriers: new BufferMemoryBarrier[] { new BufferMemoryBarrier( vertexBuffer.Buffer, Accesses.TransferWrite, Accesses.VertexAttributeRead ) } ); stagingCommands.End(); Graphics.TransferQueueFamily.HighestPriority.Submit( new SubmitInfo( commandBuffers: new CommandBuffer[] { stagingCommands } ), stagingFence ); stagingFence.Wait(); } } } listInd++; } }