private static void BlitImage( ImageAspects aspectMask, Image fromImage, IntRect fromRegion, int fromMipLevel, int fromLayerCount, Image toImage, IntRect toRegion, int toMipLevel, int toLayerCount, TransientExecutor executor) { ImageBlit blit = new ImageBlit { SrcSubresource = new ImageSubresourceLayers( aspectMask, fromMipLevel, baseArrayLayer: 0, fromLayerCount), SrcOffset1 = new Offset3D(fromRegion.Min.X, fromRegion.Min.Y, 0), SrcOffset2 = new Offset3D(fromRegion.Max.X, fromRegion.Max.Y, 1), DstSubresource = new ImageSubresourceLayers( aspectMask, toMipLevel, baseArrayLayer: 0, toLayerCount), DstOffset1 = new Offset3D(toRegion.Min.X, toRegion.Min.Y, 0), DstOffset2 = new Offset3D(toRegion.Max.X, toRegion.Max.Y, 1) }; //Execute the blit executor.ExecuteBlocking(commandBuffer => { commandBuffer.CmdBlitImage( srcImage: fromImage, srcImageLayout: ImageLayout.TransferSrcOptimal, dstImage: toImage, dstImageLayout: ImageLayout.TransferDstOptimal, regions: new [] { blit }, filter: Filter.Linear); }); }
private static void TransitionImageLayout( Image image, ImageAspects aspectMask, int baseMipLevel, int mipLevels, int baseLayer, int layers, ImageLayout oldLayout, ImageLayout newLayout, TransientExecutor executor) { //Get where this transition has to wait and what has to wait for this transition Accesses sourceAccess, destinationAccess; PipelineStages sourcePipelineStages, destinationPipelineStages; if (oldLayout == ImageLayout.Undefined && newLayout == ImageLayout.TransferDstOptimal) { sourceAccess = Accesses.None; destinationAccess = Accesses.TransferWrite; sourcePipelineStages = PipelineStages.TopOfPipe; destinationPipelineStages = PipelineStages.Transfer; } else if (oldLayout == ImageLayout.Undefined && newLayout == ImageLayout.DepthStencilAttachmentOptimal) { sourceAccess = Accesses.None; destinationAccess = Accesses.DepthStencilAttachmentRead | Accesses.DepthStencilAttachmentWrite; sourcePipelineStages = PipelineStages.TopOfPipe; destinationPipelineStages = PipelineStages.EarlyFragmentTests; } else if (oldLayout == ImageLayout.Undefined && newLayout == ImageLayout.ColorAttachmentOptimal) { sourceAccess = Accesses.None; destinationAccess = Accesses.ColorAttachmentRead | Accesses.ColorAttachmentWrite; sourcePipelineStages = PipelineStages.TopOfPipe; destinationPipelineStages = PipelineStages.ColorAttachmentOutput; } else if (oldLayout == ImageLayout.TransferDstOptimal && newLayout == ImageLayout.TransferSrcOptimal) { sourceAccess = Accesses.TransferWrite; destinationAccess = Accesses.TransferRead; sourcePipelineStages = PipelineStages.Transfer; destinationPipelineStages = PipelineStages.Transfer; } else if (oldLayout == ImageLayout.TransferDstOptimal && newLayout == ImageLayout.ShaderReadOnlyOptimal) { sourceAccess = Accesses.TransferWrite; destinationAccess = Accesses.ShaderRead; sourcePipelineStages = PipelineStages.Transfer; destinationPipelineStages = PipelineStages.FragmentShader; } else if (oldLayout == ImageLayout.TransferSrcOptimal && newLayout == ImageLayout.ShaderReadOnlyOptimal) { sourceAccess = Accesses.TransferRead; destinationAccess = Accesses.ShaderRead; sourcePipelineStages = PipelineStages.Transfer; destinationPipelineStages = PipelineStages.FragmentShader; } else { throw new Exception( $"[{nameof(DeviceTexture)}] Unsupported image transition: from: {oldLayout} to: {newLayout}"); } //Create the transition barrier var imageMemoryBarrier = new ImageMemoryBarrier( image: image, subresourceRange: new ImageSubresourceRange( aspectMask: aspectMask, baseMipLevel: baseMipLevel, levelCount: mipLevels, baseArrayLayer: baseLayer, layerCount: layers), srcAccessMask: sourceAccess, dstAccessMask: destinationAccess, oldLayout: oldLayout, newLayout: newLayout); //Execute the barrier executor.ExecuteBlocking(commandBuffer => { commandBuffer.CmdPipelineBarrier( srcStageMask: sourcePipelineStages, dstStageMask: destinationPipelineStages, dependencyFlags: Dependencies.None, memoryBarriers: null, bufferMemoryBarriers: null, imageMemoryBarriers: new [] { imageMemoryBarrier }); }); }