// Starts a transfer of raw data from the host to a device buffer public unsafe static void PushBuffer(byte *src, uint length, Vk.Buffer dst, uint dstOffset) { // Calculate transfer information uint blockCount = (uint)Mathf.Ceiling(length / (float)DEFAULT_BUFFER_SIZE); // Iterate over the transfer blocks for (uint bidx = 0; bidx < blockCount; ++bidx) { // Calculate offsets and block sizes uint blockOff = bidx * DEFAULT_BUFFER_SIZE; byte *currSrc = src + blockOff; uint currDstOffset = dstOffset + blockOff; uint currLength = Math.Min(length - blockOff, DEFAULT_BUFFER_SIZE); // Wait on the previous transfer s_pushFence.Wait(); s_pushFence.Reset(); // Map the staging buffer, and copy the memory IntPtr mapped = s_pushMemory.Map(0, currLength); System.Buffer.MemoryCopy(currSrc, mapped.ToPointer(), currLength, currLength); s_pushMemory.Unmap(); // Start recording s_pushCommands.Begin(ONE_TIME_SUBMIT_INFO); // Add the transfer command Vk.BufferCopy bc = new Vk.BufferCopy(currLength, 0, currDstOffset); s_pushCommands.CmdCopyBuffer(s_pushBuffer, dst, bc); // End recording, and submit s_pushCommands.End(); s_queue.Submit(s_pushSubmitInfo, fence: s_pushFence); } }
// Waits for the item fence to signal, checks if there is a valid fence to wait on public void WaitAvailable() { if (!IsSubmitted) { Waited = false; return; } Waited = Fence.GetStatus() != Vk.Result.Success; if (Waited) { Fence.Wait(); } Fence.Reset(); IsSubmitted = false; }
// Submits a one-time action that needs a graphics queue command buffer, will be synchronous // The command buffer will already have Begin() called when it is passed to the action, and will automatically call End() internal void SubmitScratchCommand(Action <Vk.CommandBuffer> action, Vk.Semaphore waitSem = null, Vk.PipelineStages waitStages = Vk.PipelineStages.AllGraphics, Vk.Fence waitFence = null) { // Record the command var cb = _scratchPool.AllocateBuffers(_scratchAllocInfo)[0]; cb.Begin(_scratchBeginInfo); action(cb); cb.End(); // Submit if (waitFence != null) { waitFence.Wait(); waitFence.Reset(); } Queues.Graphics.Submit(waitSem, waitStages, cb, null, _scratchFence); _scratchFence.Wait(); _scratchFence.Reset(); cb.Dispose(); }
/// <summary> /// Wait for one or more fences 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="fences">Fence handle.</param> /// <param name="waitAll"> /// The condition that must be satisfied to successfully unblock the wait. If <c>true</c> , /// then the condition is that all fences in <paramref name="fences"/> are signaled. /// Otherwise, the condition is that at least one fence in <paramref name="fences"/> is signaled. /// </param> /// <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 WaitFences(Fence[] fences, bool waitAll, long timeout = ~0) { Fence.Wait(this, fences, waitAll, timeout); }