/// <summary> /// Invalidate a range of mapped memory. /// <para> /// Must be used to guarantee that device writes to non-coherent memory are visible to the /// host. It must be called after command buffers that execute and flush (via memory /// barriers) the device writes have completed, and before the host will read or write any of /// those locations. If a range of non-coherent memory is written by the host and then /// invalidated without first being flushed, its contents are undefined. /// </para> /// <para> /// Mapping non-coherent memory does not implicitly invalidate the mapped memory, and device /// writes that have not been invalidated must be made visible before the host reads or /// overwrites them. /// </para> /// </summary> /// <param name="memoryRange">Structure describing the memory range to invalidate.</param> /// <exception cref="VulkanException">Vulkan returns an error code.</exception> public void InvalidateMappedMemoryRange(MappedMemoryRange memoryRange) { memoryRange.Prepare(); Result result = vkInvalidateMappedMemoryRanges(this, 1, &memoryRange); VulkanException.ThrowForInvalidResult(result); }
/// <summary> /// Wait for the fence to become signaled. /// <para> /// If the condition is satisfied when the command is called, then the command returns /// immediately. If the condition is not satisfied at the time the command is called, then /// the command will block and wait up to timeout nanoseconds for the condition to become satisfied. /// </para> /// </summary> /// <param name="timeout"> /// The timeout period in units of nanoseconds. Timeout is adjusted to the closest value /// allowed by the implementation-dependent timeout accuracy, which may be substantially /// longer than one nanosecond, and may be longer than the requested period. /// <para> /// If timeout is zero, then the command does not wait, but simply returns the current state /// of the fences. The result <see cref="Result.Timeout"/> will be thrown in this case if the /// condition is not satisfied, even though no actual wait was performed. /// </para> /// <para> /// If the specified timeout period expires before the condition is satisfied, the command /// throws with <see cref="Result.Timeout"/>. If the condition is satisfied before timeout /// nanoseconds has expired, the command returns successfully. /// </para> /// </param> /// <exception cref="VulkanException">Vulkan returns an error code.</exception> public void Wait(long timeout = ~0) { long handle = this; Result result = vkWaitForFences(Parent, 1, &handle, false, timeout); VulkanException.ThrowForInvalidResult(result); }
/// <summary> /// Submits semaphores or a command buffer to a queue. /// </summary> /// <param name="fence"> /// An optional handle to a fence to be signaled. If fence is not <c>null</c>, it defines a /// fence signal operation. /// </param> /// <param name="waitSemaphore"> /// Semaphore upon which to wait before the command buffer for this batch begins execution. /// If semaphore to wait on is provided, it defines a semaphore wait operation. /// </param> /// <param name="waitDstStageMask">Pipeline stages at which semaphore wait will occur.</param> /// <param name="commandBuffer">Command buffer to execute in the batch.</param> /// <param name="signalSemaphore"> /// Semaphore which will be signaled when the command buffer for this batch has completed /// execution. If semaphore to be signaled is provided, it defines a semaphore signal operation. /// </param> /// <exception cref="VulkanException">Vulkan returns an error code.</exception> public void Submit(Semaphore waitSemaphore, PipelineStages waitDstStageMask, CommandBuffer commandBuffer, Semaphore signalSemaphore, Fence fence = null) { long waitSemaphoreHandle = waitSemaphore; IntPtr commandBufferHandle = commandBuffer; long signalSemaphoreHandle = signalSemaphore; var nativeSubmit = new SubmitInfo.Native { Type = StructureType.SubmitInfo }; if (waitSemaphoreHandle != 0) { nativeSubmit.WaitSemaphoreCount = 1; nativeSubmit.WaitSemaphores = new IntPtr(&waitSemaphoreHandle); nativeSubmit.WaitDstStageMask = new IntPtr(&waitDstStageMask); } if (commandBufferHandle != IntPtr.Zero) { nativeSubmit.CommandBufferCount = 1; nativeSubmit.CommandBuffers = new IntPtr(&commandBufferHandle); } if (signalSemaphoreHandle != 0) { nativeSubmit.SignalSemaphoreCount = 1; nativeSubmit.SignalSemaphores = new IntPtr(&signalSemaphoreHandle); } Result result = vkQueueSubmit(this, 1, &nativeSubmit, fence); VulkanException.ThrowForInvalidResult(result); }
/// <summary> /// Resets the fence object. /// <para>Defines a fence unsignal operation, which resets the fence to the unsignaled state.</para> /// <para> /// If fence is already in the unsignaled state, then the command has no effect on that fence. /// </para> /// </summary> /// <exception cref="VulkanException">Vulkan returns an error code.</exception> public void Reset() { long handle = this; Result result = vkResetFences(Parent, 1, &handle); VulkanException.ThrowForInvalidResult(result); }
/// <summary> /// Returns global extension properties. /// </summary> /// <param name="layerName"> /// Is either <c>null</c> or a unicode string naming the layer to retrieve extensions from. /// When parameter is <c>null</c>, only extensions provided by the Vulkan implementation or /// by implicitly enabled layers are returned. /// </param> /// <returns>Properties of available extensions for layer.</returns> /// <exception cref="VulkanException">Vulkan returns an error code.</exception> public static ExtensionProperties[] EnumerateExtensionProperties(string layerName = null) { int dstLayerNameByteCount = Interop.String.GetMaxByteCount(layerName); var dstLayerNamePtr = stackalloc byte[dstLayerNameByteCount]; Interop.String.ToPointer(layerName, dstLayerNamePtr, dstLayerNameByteCount); int count; Result result = vkEnumerateInstanceExtensionProperties(dstLayerNamePtr, &count, null); VulkanException.ThrowForInvalidResult(result); var propertiesPtr = stackalloc ExtensionProperties.Native[count]; result = vkEnumerateInstanceExtensionProperties(dstLayerNamePtr, &count, propertiesPtr); VulkanException.ThrowForInvalidResult(result); var properties = new ExtensionProperties[count]; for (int i = 0; i < count; i++) { ExtensionProperties.FromNative(ref propertiesPtr[i], out properties[i]); } return(properties); }
/// <summary> /// Combine the data stores of pipeline caches. /// </summary> /// <param name="sourceCache">Pipeline cache to merge into this.</param> public void MergeCache(PipelineCache sourceCache) { long handle = sourceCache; Result result = vkMergePipelineCaches(Parent, this, 1, &handle); VulkanException.ThrowForInvalidResult(result); }
/// <summary> /// Submits a sequence of semaphores or command buffers to a queue. /// </summary> /// <param name="submit">Specifies a command buffer submission batch.</param> /// <param name="fence"> /// An optional handle to a fence to be signaled. If fence is not <c>null</c>, it defines a /// fence signal operation. /// </param> /// <exception cref="VulkanException">Vulkan returns an error code.</exception> public void Submit(SubmitInfo submit, Fence fence = null) { submit.ToNative(out SubmitInfo.Native nativeSubmit); Result result = vkQueueSubmit(this, 1, &nativeSubmit, fence); nativeSubmit.Free(); VulkanException.ThrowForInvalidResult(result); }
/// <summary> /// Bind device memory to a sparse resource object. /// </summary> /// <param name="bindInfo">Specifying a sparse binding submission batch.</param> /// <param name="fence"> /// An optional handle to a fence to be signaled. If fence is not <c>null</c>, it defines a /// fence signal operation. /// </param> /// <exception cref="VulkanException">Vulkan returns an error code.</exception> public void BindSparse(BindSparseInfo bindInfo, Fence fence = null) { bindInfo.ToNative(out BindSparseInfo.Native nativeBindInfo); Result result = vkQueueBindSparse(this, 1, &nativeBindInfo, fence); nativeBindInfo.Free(); VulkanException.ThrowForInvalidResult(result); }
/// <summary> /// Map a memory object into application address space. /// <para> /// It is an application error to call <see cref="Map"/> on a memory object that is already mapped. /// </para> /// <para> /// Will fail if the implementation is unable to allocate an appropriately sized contiguous /// virtual address range, e.g. due to virtual address space fragmentation or platform /// limits. In such cases, <see cref="Map"/> must return <see /// cref="Result.ErrorMemoryMapFailed"/>. The application can improve the likelihood of /// success by reducing the size of the mapped range and/or removing unneeded mappings using /// <see cref="Unmap"/>. /// </para> /// <para> /// Does not check whether the device memory is currently in use before returning the /// host-accessible pointer. The application must guarantee that any previously submitted /// command that writes to this range has completed before the host reads from or writes to /// that range, and that any previously submitted command that reads from that range has /// completed before the host writes to that region (see here for details on fulfilling such /// a guarantee). If the device memory was allocated without the <see /// cref="MemoryProperties.HostCoherent"/> set, these guarantees must be made for an extended /// range: the application must round down the start of the range to the nearest multiple of /// <see cref="PhysicalDeviceLimits.NonCoherentAtomSize"/>, and round the end of the /// range up to the nearest multiple of <see cref="PhysicalDeviceLimits.NonCoherentAtomSize"/>. /// </para> /// <para> /// While a range of device memory is mapped for host access, the application is responsible /// for synchronizing both device and host access to that memory range. /// </para> /// </summary> /// <param name="offset">A zero-based byte offset from the beginning of the memory object.</param> /// <param name="size"> /// The size of the memory range to map, or <see cref="Constant.WholeSize"/> to map from /// offset to the end of the allocation. /// </param> /// <returns> /// A pointer in which is returned a host-accessible pointer to the beginning of the mapped /// range. This pointer minus offset must be aligned to at least <see cref="PhysicalDeviceLimits.MinMemoryMapAlignment"/>. /// </returns> /// <exception cref="VulkanException">Vulkan returns an error code.</exception> public IntPtr Map(long offset, long size) { IntPtr ptr; Result result = vkMapMemory(Parent, this, offset, size, 0, &ptr); VulkanException.ThrowForInvalidResult(result); return(ptr); }
/// <summary> /// Retrieve the status of an event object. Upon success, the command returns the state of /// the event object with the following return codes: /// <para>* <see cref="Result.EventSet"/> - The event is signaled</para> /// <para>* <see cref="Result.EventReset"/> - The event is unsignaled</para> /// </summary> /// <returns><see cref="Result.EventSet"/> if the event is signaled; otherwise <see cref="Result.EventReset"/>.</returns> /// <exception cref="VulkanException">Vulkan returns an error code.</exception> public Result GetStatus() { Result result = vkGetEventStatus(Parent, this); if (result != Result.EventSet && result != Result.EventReset) { VulkanException.ThrowForInvalidResult(result); } return(result); }
/// <summary> /// Return the status of a fence. Upon success, returns the status of the fence object, with /// the following return codes: /// <para>* <see cref="Result.Success"/> - The fence is signaled</para> /// <para>* <see cref="Result.NotReady"/> - The fence is unsignaled</para> /// </summary> /// <returns><see cref="Result.Success"/> if the fence is signaled; otherwise <see cref="Result.NotReady"/>.</returns> /// <exception cref="VulkanException">Vulkan returns an error code.</exception> public Result GetStatus() { Result result = vkGetFenceStatus(Parent, this); if (result != Result.Success && result != Result.NotReady) { VulkanException.ThrowForInvalidResult(result); } return(result); }
/// <summary> /// Free descriptor set. /// </summary> /// <exception cref="VulkanException">Vulkan returns an error code.</exception> public override void Dispose() { if (!Disposed) { long handle = this; Result result = vkFreeDescriptorSets(Parent.Parent, Parent, 1, &handle); VulkanException.ThrowForInvalidResult(result); } base.Dispose(); }
internal CommandPool(Device parent, CommandPoolCreateInfo *createInfo, ref AllocationCallbacks?allocator) { Parent = parent; Allocator = allocator; createInfo->Prepare(); long handle; Result result = vkCreateCommandPool(Parent, createInfo, NativeAllocator, &handle); VulkanException.ThrowForInvalidResult(result); Handle = handle; }
/// <summary> /// Invalidate ranges of mapped memory objects. /// <para> /// Must be used to guarantee that device writes to non-coherent memory are visible to the /// host. It must be called after command buffers that execute and flush (via memory /// barriers) the device writes have completed, and before the host will read or write any of /// those locations. If a range of non-coherent memory is written by the host and then /// invalidated without first being flushed, its contents are undefined. /// </para> /// <para> /// Mapping non-coherent memory does not implicitly invalidate the mapped memory, and device /// writes that have not been invalidated must be made visible before the host reads or /// overwrites them. /// </para> /// </summary> /// <param name="memoryRanges">Structures describing the memory ranges to invalidate.</param> /// <exception cref="VulkanException">Vulkan returns an error code.</exception> public void InvalidateMappedMemoryRanges(params MappedMemoryRange[] memoryRanges) { int count = memoryRanges?.Length ?? 0; for (int i = 0; i < count; i++) memoryRanges[i].Prepare(); fixed (MappedMemoryRange* memoryRangesPtr = memoryRanges) { Result result = vkInvalidateMappedMemoryRanges(this, count, memoryRangesPtr); VulkanException.ThrowForInvalidResult(result); } }
internal Device(PhysicalDevice parent, ref DeviceCreateInfo createInfo, ref AllocationCallbacks? allocator) { Parent = parent; Allocator = allocator; createInfo.ToNative(out DeviceCreateInfo.Native nativeCreateInfo); IntPtr handle; Result result = vkCreateDevice(Parent.Handle, &nativeCreateInfo, NativeAllocator, &handle); nativeCreateInfo.Free(); VulkanException.ThrowForInvalidResult(result); Handle = handle; }
internal ImageView(Device parent, Image image, ImageViewCreateInfo *createInfo, ref AllocationCallbacks?allocator) { Parent = parent; Allocator = allocator; createInfo->Prepare(image); long handle; Result result = vkCreateImageView(Parent, createInfo, NativeAllocator, &handle); VulkanException.ThrowForInvalidResult(result); Handle = handle; }
internal static void Wait(Device parent, Fence[] fences, bool waitAll, long timeout) { int count = fences?.Length ?? 0; long *handles = stackalloc long[count]; for (int i = 0; i < count; i++) { handles[i] = fences[i]; } Result result = vkWaitForFences(parent, count, handles, waitAll, timeout); VulkanException.ThrowForInvalidResult(result); }
internal DeviceMemory(Device parent, MemoryAllocateInfo *allocateInfo, ref AllocationCallbacks?allocator) { Parent = parent; Allocator = allocator; long handle; allocateInfo->Prepare(); Result result = vkAllocateMemory(parent, allocateInfo, NativeAllocator, &handle); VulkanException.ThrowForInvalidResult(result); Handle = handle; }
internal static void Reset(Device parent, Fence[] fences) { int count = fences?.Length ?? 0; long *handles = stackalloc long[count]; for (int i = 0; i < count; i++) { handles[i] = fences[i]; } Result result = vkResetFences(parent, count, handles); VulkanException.ThrowForInvalidResult(result); }
internal static void Free(DescriptorPool parent, DescriptorSet[] descriptorSets) { int count = descriptorSets?.Length ?? 0; var descriptorSetsPtr = stackalloc long[count]; for (int i = 0; i < count; i++) { descriptorSetsPtr[i] = descriptorSets[i]; } Result result = vkFreeDescriptorSets(parent.Parent, parent, count, descriptorSetsPtr); VulkanException.ThrowForInvalidResult(result); }
internal Semaphore(Device parent, ref AllocationCallbacks?allocator) { Parent = parent; Allocator = allocator; var createInfo = new SemaphoreCreateInfo(); createInfo.Prepare(); long handle; Result result = vkCreateSemaphore(Parent, &createInfo, NativeAllocator, &handle); VulkanException.ThrowForInvalidResult(result); Handle = handle; }
/// <summary> /// Combine the data stores of pipeline caches. /// </summary> /// <param name="sourceCaches">Pipeline caches to merge into this.</param> public void MergeCaches(params PipelineCache[] sourceCaches) { int count = sourceCaches?.Length ?? 0; var sourceCachesPtr = stackalloc long[count]; for (int i = 0; i < count; i++) { sourceCachesPtr[i] = sourceCaches[i].Handle; } Result result = vkMergePipelineCaches(Parent, this, count, sourceCachesPtr); VulkanException.ThrowForInvalidResult(result); }
internal DescriptorPool(Device parent, ref DescriptorPoolCreateInfo createInfo, ref AllocationCallbacks?allocator) { Parent = parent; Allocator = allocator; fixed(DescriptorPoolSize *poolSizesPtr = createInfo.PoolSizes) { createInfo.ToNative(out DescriptorPoolCreateInfo.Native nativeCreateInfo, poolSizesPtr); long handle; Result result = vkCreateDescriptorPool(Parent, &nativeCreateInfo, NativeAllocator, &handle); VulkanException.ThrowForInvalidResult(result); Handle = handle; } }
/// <summary> /// Create a new Vulkan instance. /// </summary> /// <param name="createInfo"> /// An instance of <see cref="InstanceCreateInfo"/> controlling creation of the instance. /// </param> /// <param name="allocator">Controls host memory allocation.</param> /// <exception cref="VulkanException">Vulkan returns an error code.</exception> public Instance(InstanceCreateInfo createInfo = default(InstanceCreateInfo), AllocationCallbacks?allocator = null) { Allocator = allocator; createInfo.ToNative(out InstanceCreateInfo.Native nativeCreateInfo); IntPtr handle; Result result = vkCreateInstance(&nativeCreateInfo, NativeAllocator, &handle); nativeCreateInfo.Free(); VulkanException.ThrowForInvalidResult(result); Handle = handle; }
internal ShaderModule(Device parent, ref ShaderModuleCreateInfo createInfo, ref AllocationCallbacks?allocator) { Parent = parent; Allocator = allocator; fixed(byte *codePtr = createInfo.Code) { createInfo.ToNative(out ShaderModuleCreateInfo.Native nativeCreateInfo, codePtr); long handle; Result result = vkCreateShaderModule(Parent, &nativeCreateInfo, NativeAllocator, &handle); VulkanException.ThrowForInvalidResult(result); Handle = handle; } }
internal Image(Device parent, ref ImageCreateInfo createInfo, ref AllocationCallbacks?allocator) { Parent = parent; Allocator = allocator; fixed(int *queueFamilyIndicesPtr = createInfo.QueueFamilyIndices) { createInfo.ToNative(out ImageCreateInfo.Native nativeCreateInfo, queueFamilyIndicesPtr); long handle; Result result = vkCreateImage(parent, &nativeCreateInfo, NativeAllocator, &handle); VulkanException.ThrowForInvalidResult(result); Handle = handle; } }
internal DescriptorSetLayout(Device parent, ref DescriptorSetLayoutCreateInfo createInfo, ref AllocationCallbacks?allocator) { Parent = parent; Allocator = allocator; createInfo.ToNative(out DescriptorSetLayoutCreateInfo.Native nativeCreateInfo); long handle; Result result = vkCreateDescriptorSetLayout(Parent, &nativeCreateInfo, NativeAllocator, &handle); nativeCreateInfo.Free(); VulkanException.ThrowForInvalidResult(result); Handle = handle; }
/// <summary> /// Get the data store from a pipeline cache. /// </summary> /// <returns>Buffer.</returns> /// <exception cref="VulkanException">Vulkan returns an error code.</exception> public byte[] GetData() { int size; Result result = vkGetPipelineCacheData(Parent, this, &size, null); VulkanException.ThrowForInvalidResult(result); var data = new byte[size]; fixed(byte *dataPtr = data) result = vkGetPipelineCacheData(Parent, this, &size, dataPtr); VulkanException.ThrowForInvalidResult(result); return(data); }
internal PipelineCache(Device parent, ref PipelineCacheCreateInfo createInfo, ref AllocationCallbacks?allocator) { Parent = parent; Allocator = allocator; fixed(byte *initialDataPtr = createInfo.InitialData) { createInfo.ToNative(out PipelineCacheCreateInfo.Native nativeCreateInfo, initialDataPtr); long handle; Result result = vkCreatePipelineCache(Parent, &nativeCreateInfo, NativeAllocator, &handle); VulkanException.ThrowForInvalidResult(result); Handle = handle; } }
internal RenderPass(Device parent, ref RenderPassCreateInfo createInfo, ref AllocationCallbacks?allocator) { Parent = parent; Allocator = allocator; fixed(AttachmentDescription *attachmentsPtr = createInfo.Attachments) fixed(SubpassDependency * dependenciesPtr = createInfo.Dependencies) { createInfo.ToNative(out RenderPassCreateInfo.Native nativeCreateInfo, attachmentsPtr, dependenciesPtr); long handle; Result result = vkCreateRenderPass(Parent, &nativeCreateInfo, NativeAllocator, &handle); nativeCreateInfo.Free(); VulkanException.ThrowForInvalidResult(result); Handle = handle; } }