public void Free(VkMemoryBlock block) { _freeBlocks.Add(block); #if DEBUG RemoveAllocatedBlock(block); #endif }
public VkDeviceBuffer( VkRenderContext rc, ulong size, VkBufferUsageFlags usage, VkMemoryPropertyFlags memoryProperties, bool dynamic) { _rc = rc; usage |= VkBufferUsageFlags.TransferSrc; _usage = usage; _memoryProperties = memoryProperties; _isDynamic = dynamic; VkBufferCreateInfo bufferCI = VkBufferCreateInfo.New(); bufferCI.size = size; bufferCI.usage = _usage; VkResult result = vkCreateBuffer(rc.Device, ref bufferCI, null, out _buffer); CheckResult(result); vkGetBufferMemoryRequirements(rc.Device, _buffer, out _bufferMemoryRequirements); _bufferCapacity = _bufferMemoryRequirements.size; uint memoryType = FindMemoryType(rc.PhysicalDevice, _bufferMemoryRequirements.memoryTypeBits, memoryProperties); VkMemoryBlock memoryToken = rc.MemoryManager.Allocate( memoryType, _bufferMemoryRequirements.size, _bufferMemoryRequirements.alignment); _memory = memoryToken; vkBindBufferMemory(rc.Device, _buffer, _memory.DeviceMemory, _memory.Offset); }
private void CheckAllocatedBlock(VkMemoryBlock block) { foreach (VkMemoryBlock oldBlock in _allocatedBlocks) { Debug.Assert(!BlocksOverlap(block, oldBlock), "Allocated blocks have overlapped."); } _allocatedBlocks.Add(block); }
public void Free(VkMemoryBlock block) { foreach (ChunkAllocator chunk in _allocators) { if (chunk.Memory == block.DeviceMemory) { chunk.Free(block); } } }
public bool Allocate(ulong size, ulong alignment, out VkMemoryBlock block) { checked { for (int i = 0; i < _freeBlocks.Count; i++) { VkMemoryBlock freeBlock = _freeBlocks[i]; ulong alignedBlockSize = freeBlock.Size; if (freeBlock.Offset % alignment != 0) { ulong alignmentCorrection = (alignment - freeBlock.Offset % alignment); if (alignedBlockSize <= alignmentCorrection) { continue; } alignedBlockSize -= alignmentCorrection; } if (alignedBlockSize >= size) // Valid match -- split it and return. { _freeBlocks.Remove(freeBlock); freeBlock.Size = alignedBlockSize; if ((freeBlock.Offset % alignment) != 0) { freeBlock.Offset += alignment - (freeBlock.Offset % alignment); } block = freeBlock; if (alignedBlockSize != size) { VkMemoryBlock splitBlock = new VkMemoryBlock( freeBlock.DeviceMemory, freeBlock.Offset + size, freeBlock.Size - size, _memoryTypeIndex); _freeBlocks.Add(splitBlock); block = freeBlock; block.Size = size; } #if DEBUG CheckAllocatedBlock(block); #endif _totalAllocatedBytes += alignedBlockSize; return(true); } } block = null; return(false); } }
private bool BlocksOverlap(VkMemoryBlock first, VkMemoryBlock second) { ulong firstStart = first.Offset; ulong firstEnd = first.Offset + first.Size; ulong secondStart = second.Offset; ulong secondEnd = second.Offset + second.Size; return(firstStart <= secondStart && firstEnd > secondStart || firstStart >= secondStart && firstEnd <= secondEnd || firstStart < secondEnd && firstEnd >= secondEnd || firstStart <= secondStart && firstEnd >= secondEnd); }
public bool Allocate(ulong size, ulong alignment, out VkMemoryBlock block) { foreach (ChunkAllocator allocator in _allocators) { if (allocator.Allocate(size, alignment, out block)) { return(true); } } ChunkAllocator newAllocator = new ChunkAllocator(_device, _memoryTypeIndex); _allocators.Add(newAllocator); return(newAllocator.Allocate(size, alignment, out block)); }
public ChunkAllocator(VkDevice device, uint memoryTypeIndex) { _device = device; _memoryTypeIndex = memoryTypeIndex; VkMemoryAllocateInfo memoryAI = VkMemoryAllocateInfo.New(); memoryAI.allocationSize = _totalMemorySize; memoryAI.memoryTypeIndex = _memoryTypeIndex; VkResult result = vkAllocateMemory(_device, ref memoryAI, null, out _memory); CheckResult(result); VkMemoryBlock initialBlock = new VkMemoryBlock(_memory, 0, _totalMemorySize, _memoryTypeIndex); _freeBlocks.Add(initialBlock); }
public static void CreateImage( VkDevice device, VkPhysicalDevice physicalDevice, VkDeviceMemoryManager memoryManager, uint width, uint height, uint arrayLayers, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, out VkImage image, out VkMemoryBlock memory) { VkImageCreateInfo imageCI = VkImageCreateInfo.New(); imageCI.imageType = VkImageType.Image2D; imageCI.extent.width = width; imageCI.extent.height = height; imageCI.extent.depth = 1; imageCI.mipLevels = 1; imageCI.arrayLayers = arrayLayers; imageCI.format = format; imageCI.tiling = tiling; imageCI.initialLayout = VkImageLayout.Preinitialized; imageCI.usage = usage; imageCI.sharingMode = VkSharingMode.Exclusive; imageCI.samples = VkSampleCountFlags.Count1; VkResult result = vkCreateImage(device, ref imageCI, null, out image); CheckResult(result); vkGetImageMemoryRequirements(device, image, out VkMemoryRequirements memRequirements); VkMemoryBlock memoryToken = memoryManager.Allocate( FindMemoryType(physicalDevice, memRequirements.memoryTypeBits, properties), memRequirements.size, memRequirements.alignment); memory = memoryToken; result = vkBindImageMemory(device, image, memory.DeviceMemory, memory.Offset); CheckResult(result); }
private void EnsureBufferSize(int dataSizeInBytes) { if (_bufferCapacity < (ulong)dataSizeInBytes) { VkBufferCreateInfo newBufferCI = VkBufferCreateInfo.New(); newBufferCI.size = (ulong)dataSizeInBytes; newBufferCI.usage = _usage | VkBufferUsageFlags.TransferDst; VkResult result = vkCreateBuffer(_rc.Device, ref newBufferCI, null, out VkBuffer newBuffer); CheckResult(result); vkGetBufferMemoryRequirements(_rc.Device, newBuffer, out VkMemoryRequirements newMemoryRequirements); uint memoryType = FindMemoryType(_rc.PhysicalDevice, newMemoryRequirements.memoryTypeBits, _memoryProperties); VkMemoryBlock newMemory = _rc.MemoryManager.Allocate( memoryType, newMemoryRequirements.size, newMemoryRequirements.alignment); result = vkBindBufferMemory(_rc.Device, newBuffer, newMemory.DeviceMemory, newMemory.Offset); CheckResult(result); if (_bufferDataSize > 0) { VkCommandBuffer copyCmd = _rc.BeginOneTimeCommands(); VkBufferCopy region = new VkBufferCopy(); region.size = _bufferDataSize; vkCmdCopyBuffer(copyCmd, _buffer, newBuffer, 1, ref region); _rc.EndOneTimeCommands(copyCmd, VkFence.Null); } _rc.MemoryManager.Free(_memory); vkDestroyBuffer(_rc.Device, _buffer, null); _buffer = newBuffer; _memory = newMemory; _bufferCapacity = (ulong)dataSizeInBytes; } }
public VkCubemapTexture( VkDevice device, VkPhysicalDevice physicalDevice, VkDeviceMemoryManager memoryManager, VkRenderContext rc, IntPtr pixelsFront, IntPtr pixelsBack, IntPtr pixelsLeft, IntPtr pixelsRight, IntPtr pixelsTop, IntPtr pixelsBottom, int width, int height, PixelFormat format) { _device = device; _physicalDevice = physicalDevice; _rc = rc; _memoryManager = memoryManager; Width = width; Height = height; _format = format; _vkFormat = VkFormats.VeldridToVkPixelFormat(_format); vkGetPhysicalDeviceImageFormatProperties( _physicalDevice, _vkFormat, VkImageType.Image2D, VkImageTiling.Linear, VkImageUsageFlags.Sampled, VkImageCreateFlags.CubeCompatible, out VkImageFormatProperties linearProps); vkGetPhysicalDeviceImageFormatProperties( _physicalDevice, _vkFormat, VkImageType.Image2D, VkImageTiling.Optimal, VkImageUsageFlags.Sampled, VkImageCreateFlags.CubeCompatible, out VkImageFormatProperties optimalProps); bool useSingleStagingBuffer = linearProps.maxArrayLayers >= 6; VkImageCreateInfo imageCI = VkImageCreateInfo.New(); imageCI.imageType = VkImageType.Image2D; imageCI.flags = VkImageCreateFlags.CubeCompatible; imageCI.format = _vkFormat; imageCI.extent.width = (uint)width; imageCI.extent.height = (uint)height; imageCI.extent.depth = 1; imageCI.mipLevels = 1; imageCI.arrayLayers = 6; imageCI.samples = VkSampleCountFlags.Count1; imageCI.tiling = useSingleStagingBuffer ? VkImageTiling.Linear : VkImageTiling.Optimal; imageCI.usage = VkImageUsageFlags.Sampled | VkImageUsageFlags.TransferDst; imageCI.initialLayout = VkImageLayout.Preinitialized; VkResult result = vkCreateImage(_device, ref imageCI, null, out _image); CheckResult(result); vkGetImageMemoryRequirements(_device, _image, out VkMemoryRequirements memReqs); uint memoryType = FindMemoryType(_physicalDevice, memReqs.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal); _memory = memoryManager.Allocate(memoryType, memReqs.size, memReqs.alignment); vkBindImageMemory(_device, _image, _memory.DeviceMemory, _memory.Offset); if (useSingleStagingBuffer) { CopyDataSingleStagingBuffer(pixelsFront, pixelsBack, pixelsLeft, pixelsRight, pixelsTop, pixelsBottom, memReqs); } else { CopyDataMultiImage(pixelsFront, pixelsBack, pixelsLeft, pixelsRight, pixelsTop, pixelsBottom); } TransitionImageLayout(_image, (uint)MipLevels, 0, 6, VkImageLayout.TransferDstOptimal, VkImageLayout.ShaderReadOnlyOptimal); _imageLayout = VkImageLayout.ShaderReadOnlyOptimal; }
private void CopyDataSingleStagingBuffer(IntPtr pixelsFront, IntPtr pixelsBack, IntPtr pixelsLeft, IntPtr pixelsRight, IntPtr pixelsTop, IntPtr pixelsBottom, VkMemoryRequirements memReqs) { VkBufferCreateInfo bufferCI = VkBufferCreateInfo.New(); bufferCI.size = memReqs.size; bufferCI.usage = VkBufferUsageFlags.TransferSrc; vkCreateBuffer(_device, ref bufferCI, null, out VkBuffer stagingBuffer); vkGetBufferMemoryRequirements(_device, stagingBuffer, out VkMemoryRequirements stagingMemReqs); VkMemoryBlock stagingMemory = _memoryManager.Allocate( FindMemoryType( _physicalDevice, stagingMemReqs.memoryTypeBits, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent), stagingMemReqs.size, stagingMemReqs.alignment); VkResult result = vkBindBufferMemory(_device, stagingBuffer, stagingMemory.DeviceMemory, 0); CheckResult(result); StackList <IntPtr, Size6IntPtr> faces = new StackList <IntPtr, Size6IntPtr>(); faces.Add(pixelsRight); faces.Add(pixelsLeft); faces.Add(pixelsTop); faces.Add(pixelsBottom); faces.Add(pixelsBack); faces.Add(pixelsFront); for (uint i = 0; i < 6; i++) { VkImageSubresource subresource; subresource.aspectMask = VkImageAspectFlags.Color; subresource.arrayLayer = i; subresource.mipLevel = 0; vkGetImageSubresourceLayout(_device, _image, ref subresource, out VkSubresourceLayout faceLayout); void *mappedPtr; result = vkMapMemory(_device, stagingMemory.DeviceMemory, faceLayout.offset, faceLayout.size, 0, &mappedPtr); CheckResult(result); Buffer.MemoryCopy((void *)faces[i], mappedPtr, faceLayout.size, faceLayout.size); vkUnmapMemory(_device, stagingMemory.DeviceMemory); } StackList <VkBufferImageCopy, Size512Bytes> copyRegions = new StackList <VkBufferImageCopy, Size512Bytes>(); for (uint i = 0; i < 6; i++) { VkImageSubresource subres; subres.aspectMask = VkImageAspectFlags.Color; subres.mipLevel = 0; subres.arrayLayer = i; vkGetImageSubresourceLayout(_device, _image, ref subres, out VkSubresourceLayout layout); VkBufferImageCopy copyRegion; copyRegion.bufferOffset = layout.offset; copyRegion.bufferImageHeight = 0; copyRegion.bufferRowLength = 0; copyRegion.imageExtent.width = (uint)Width; copyRegion.imageExtent.height = (uint)Height; copyRegion.imageExtent.depth = 1; copyRegion.imageOffset.x = 0; copyRegion.imageOffset.y = 0; copyRegion.imageOffset.z = 0; copyRegion.imageSubresource.baseArrayLayer = i; copyRegion.imageSubresource.aspectMask = VkImageAspectFlags.Color; copyRegion.imageSubresource.layerCount = 1; copyRegion.imageSubresource.mipLevel = 0; copyRegions.Add(copyRegion); } VkFenceCreateInfo fenceCI = VkFenceCreateInfo.New(); result = vkCreateFence(_device, ref fenceCI, null, out VkFence copyFence); CheckResult(result); TransitionImageLayout(_image, (uint)MipLevels, 0, 6, _imageLayout, VkImageLayout.TransferDstOptimal); VkCommandBuffer copyCmd = _rc.BeginOneTimeCommands(); vkCmdCopyBufferToImage(copyCmd, stagingBuffer, _image, VkImageLayout.TransferDstOptimal, copyRegions.Count, (IntPtr)copyRegions.Data); _rc.EndOneTimeCommands(copyCmd, copyFence); result = vkWaitForFences(_device, 1, ref copyFence, true, ulong.MaxValue); CheckResult(result); vkDestroyBuffer(_device, stagingBuffer, null); _memoryManager.Free(stagingMemory); }
public VkTexture2D( VkDevice device, VkPhysicalDevice physicalDevice, VkDeviceMemoryManager memoryManager, VkRenderContext rc, int mipLevels, int width, int height, PixelFormat veldridFormat, DeviceTextureCreateOptions createOptions) { _device = device; _physicalDevice = physicalDevice; _memoryManager = memoryManager; _rc = rc; MipLevels = mipLevels; _width = width; _height = height; _createOptions = createOptions; if (createOptions == DeviceTextureCreateOptions.DepthStencil) { Format = VkFormat.D16Unorm; } else { Format = VkFormats.VeldridToVkPixelFormat(veldridFormat); } _veldridFormat = veldridFormat; VkImageCreateInfo imageCI = VkImageCreateInfo.New(); imageCI.mipLevels = (uint)mipLevels; imageCI.arrayLayers = 1; imageCI.imageType = VkImageType.Image2D; imageCI.extent.width = (uint)width; imageCI.extent.height = (uint)height; imageCI.extent.depth = 1; imageCI.initialLayout = VkImageLayout.Preinitialized; // TODO: Use proper VkImageLayout values and transitions. imageCI.usage = VkImageUsageFlags.TransferDst | VkImageUsageFlags.Sampled; if (createOptions == DeviceTextureCreateOptions.RenderTarget) { imageCI.usage |= VkImageUsageFlags.ColorAttachment; } else if (createOptions == DeviceTextureCreateOptions.DepthStencil) { imageCI.usage |= VkImageUsageFlags.DepthStencilAttachment; } imageCI.tiling = createOptions == DeviceTextureCreateOptions.DepthStencil ? VkImageTiling.Optimal : VkImageTiling.Optimal; imageCI.format = Format; imageCI.samples = VkSampleCountFlags.Count1; VkResult result = vkCreateImage(device, ref imageCI, null, out _image); CheckResult(result); vkGetImageMemoryRequirements(_device, _image, out VkMemoryRequirements memoryRequirements); VkMemoryBlock memoryToken = memoryManager.Allocate( FindMemoryType( _physicalDevice, memoryRequirements.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal), memoryRequirements.size, memoryRequirements.alignment); _memory = memoryToken; vkBindImageMemory(_device, _image, _memory.DeviceMemory, _memory.Offset); }
public void Free(VkMemoryBlock block) { GetAllocator(block.MemoryTypeIndex).Free(block); }
private void RemoveAllocatedBlock(VkMemoryBlock block) { Debug.Assert(_allocatedBlocks.Remove(block), "Unable to remove a supposedly allocated block."); }