예제 #1
0
        private MemoryAlloc AllocateFromBlock(MemoryType type, ulong size, ulong alignment, bool linear)
        {
            if (type.BlockSize < size)
            {
                throw new OutOfMemoryException();
            }
            alignment = GraphicsUtility.CombineAlignment(alignment, type.MinAlignment);
            var pool = linear ? memoryPoolsLinear[type.Index] : memoryPoolsNonLinear[type.Index];

            foreach (var block in pool)
            {
                var blockNode = block.TryAllocate(size, alignment);
                if (blockNode != null)
                {
                    return(new MemoryAlloc(this, block, blockNode));
                }
            }
            var newBlockMemory = TryAllocateDeviceMemory(type, type.BlockSize, null);

            if (newBlockMemory == null)
            {
                throw new OutOfMemoryException();
            }
            var newBlock     = new MemoryBlock(newBlockMemory);
            var newBlockNode = newBlock.TryAllocate(size, alignment);

            if (newBlockNode == null)
            {
                throw new OutOfMemoryException();
            }
            pool.Add(newBlock);
            return(new MemoryAlloc(this, newBlock, newBlockNode));
        }
예제 #2
0
        private static ulong GetAlignmentForBufferUsage(PlatformRenderContext ctx, SharpVulkan.BufferUsageFlags usage)
        {
            ulong alignment = 1;

            if ((usage & SharpVulkan.BufferUsageFlags.UniformBuffer) != 0)
            {
                alignment = GraphicsUtility.CombineAlignment(alignment, ctx.PhysicalDeviceLimits.MinUniformBufferOffsetAlignment);
            }
            return(alignment);
        }
예제 #3
0
        public void SetData(int level, int x, int y, int width, int height, IntPtr data)
        {
            var dataSize = GraphicsUtility.CalculateImageDataSize(Format, width, height);

            if (IsPvrtc1Format(Format))
            {
                if (x != 0 || y != 0 || width != Width || height != Height)
                {
                    throw new NotSupportedException();
                }
                if (context.NextFenceValue <= WriteFenceValue)
                {
                    context.Flush();
                }
                context.WaitForFence(WriteFenceValue);
                var dstData = Context.MemoryAllocator.Map(memory);
                try {
                    GraphicsUtility.CopyMemory(dstData, data, dataSize);
                } finally {
                    Context.MemoryAllocator.Unmap(memory);
                }
            }
            else
            {
                ulong bufferOffsetAlignment = 4;
                bufferOffsetAlignment = GraphicsUtility.CombineAlignment(bufferOffsetAlignment, (ulong)Format.GetSize());
                bufferOffsetAlignment = GraphicsUtility.CombineAlignment(bufferOffsetAlignment, context.PhysicalDeviceLimits.OptimalBufferCopyOffsetAlignment);
                var uploadBufferAlloc = context.AllocateUploadBuffer((ulong)dataSize, bufferOffsetAlignment);
                GraphicsUtility.CopyMemory(uploadBufferAlloc.Data, data, dataSize);
                context.EndRenderPass();
                context.EnsureCommandBuffer();
                var preMemoryBarrier = new SharpVulkan.ImageMemoryBarrier {
                    StructureType         = SharpVulkan.StructureType.ImageMemoryBarrier,
                    Image                 = image,
                    OldLayout             = SharpVulkan.ImageLayout.ShaderReadOnlyOptimal,
                    NewLayout             = SharpVulkan.ImageLayout.TransferDestinationOptimal,
                    SourceAccessMask      = SharpVulkan.AccessFlags.ShaderRead,
                    DestinationAccessMask = SharpVulkan.AccessFlags.TransferWrite,
                    SubresourceRange      = new SharpVulkan.ImageSubresourceRange(SharpVulkan.ImageAspectFlags.Color, 0, 1, (uint)level, 1)
                };
                context.CommandBuffer.PipelineBarrier(
                    SharpVulkan.PipelineStageFlags.VertexShader | SharpVulkan.PipelineStageFlags.FragmentShader,
                    SharpVulkan.PipelineStageFlags.Transfer, SharpVulkan.DependencyFlags.None,
                    0, null, 0, null, 1, &preMemoryBarrier);
                var copyRegion = new SharpVulkan.BufferImageCopy {
                    BufferOffset      = uploadBufferAlloc.BufferOffset,
                    BufferRowLength   = (uint)width,
                    BufferImageHeight = (uint)height,
                    ImageOffset       = new SharpVulkan.Offset3D(x, y, 0),
                    ImageExtent       = new SharpVulkan.Extent3D((uint)width, (uint)height, 1),
                    ImageSubresource  = new SharpVulkan.ImageSubresourceLayers(SharpVulkan.ImageAspectFlags.Color, 0, 1, (uint)level)
                };
                context.CommandBuffer.CopyBufferToImage(
                    uploadBufferAlloc.Buffer, image, SharpVulkan.ImageLayout.TransferDestinationOptimal, 1, &copyRegion);
                var postMemoryBarrier = new SharpVulkan.ImageMemoryBarrier {
                    StructureType         = SharpVulkan.StructureType.ImageMemoryBarrier,
                    Image                 = image,
                    OldLayout             = SharpVulkan.ImageLayout.TransferDestinationOptimal,
                    NewLayout             = SharpVulkan.ImageLayout.ShaderReadOnlyOptimal,
                    SourceAccessMask      = SharpVulkan.AccessFlags.TransferWrite,
                    DestinationAccessMask = SharpVulkan.AccessFlags.ShaderRead,
                    SubresourceRange      = new SharpVulkan.ImageSubresourceRange(SharpVulkan.ImageAspectFlags.Color, 0, 1, (uint)level, 1)
                };
                context.CommandBuffer.PipelineBarrier(
                    SharpVulkan.PipelineStageFlags.Transfer,
                    SharpVulkan.PipelineStageFlags.VertexShader | SharpVulkan.PipelineStageFlags.FragmentShader,
                    SharpVulkan.DependencyFlags.None, 0, null, 0, null, 1, &postMemoryBarrier);
            }
        }