private void FreeAllHandles() { int currentBlockIndex = 0; EntryStorageBlock block = _blocks[currentBlockIndex]; uint currentOffset = 0; for (uint i = 0; i < _totalEntries; i++) { if (currentOffset == block.TotalSize) { currentBlockIndex += 1; block = _blocks[currentBlockIndex]; currentOffset = 0; } uint id = Unsafe.Read <byte>(block.BasePtr + currentOffset); if (id == 0) { currentBlockIndex += 1; block = _blocks[currentBlockIndex]; currentOffset = 0; id = Unsafe.Read <byte>(block.BasePtr + currentOffset); } Debug.Assert(id != 0); currentOffset += 1; byte *entryBasePtr = block.BasePtr + currentOffset; switch (id) { case BeginEntryID: currentOffset += BeginEntrySize; break; case ClearColorTargetID: currentOffset += ClearColorTargetEntrySize; break; case ClearDepthTargetID: currentOffset += ClearDepthTargetEntrySize; break; case DrawEntryID: currentOffset += DrawEntrySize; break; case EndEntryID: currentOffset += EndEntrySize; break; case SetFramebufferEntryID: ref NoAllocSetFramebufferEntry sfbe = ref Unsafe.AsRef <NoAllocSetFramebufferEntry>(entryBasePtr); sfbe.Framebuffer.Free(); currentOffset += SetFramebufferEntrySize; break; case SetIndexBufferEntryID: ref NoAllocSetIndexBufferEntry sibe = ref Unsafe.AsRef <NoAllocSetIndexBufferEntry>(entryBasePtr); sibe.IndexBuffer.Free(); currentOffset += SetIndexBufferEntrySize; break; case SetPipelineEntryID: ref NoAllocSetPipelineEntry spe = ref Unsafe.AsRef <NoAllocSetPipelineEntry>(entryBasePtr); spe.Pipeline.Free(); currentOffset += SetPipelineEntrySize; break; case SetResourceSetEntryID: ref NoAllocSetResourceSetEntry srse = ref Unsafe.AsRef <NoAllocSetResourceSetEntry>(entryBasePtr); srse.ResourceSet.Free(); currentOffset += SetResourceSetEntrySize; break; case SetScissorRectEntryID: currentOffset += SetScissorRectEntrySize; break; case SetVertexBufferEntryID: ref NoAllocSetVertexBufferEntry svbe = ref Unsafe.AsRef <NoAllocSetVertexBufferEntry>(entryBasePtr); svbe.VertexBuffer.Free(); currentOffset += SetVertexBufferEntrySize; break; case SetViewportEntryID: currentOffset += SetViewportEntrySize; break; case UpdateBufferEntryID: ref NoAllocUpdateBufferEntry ube = ref Unsafe.AsRef <NoAllocUpdateBufferEntry>(entryBasePtr); ube.Buffer.Free(); ube.StagingBlock.GCHandle.Free(); currentOffset += UpdateBufferEntrySize; break; case UpdateTextureEntryID: ref NoAllocUpdateTextureEntry ute = ref Unsafe.AsRef <NoAllocUpdateTextureEntry>(entryBasePtr); ute.Texture.Free(); ute.StagingBlock.GCHandle.Free(); currentOffset += UpdateTextureEntrySize; break; case UpdateTextureCubeEntryID: ref NoAllocUpdateTextureCubeEntry utce = ref Unsafe.AsRef <NoAllocUpdateTextureCubeEntry>(entryBasePtr); utce.Texture.Free(); utce.StagingBlock.GCHandle.Free(); currentOffset += UpdateTextureCubeEntrySize; break; default: throw new InvalidOperationException("Invalid entry ID: " + id); } } }
public void ExecuteAll(OpenGLCommandExecutor executor) { int currentBlockIndex = 0; EntryStorageBlock block = _blocks[currentBlockIndex]; uint currentOffset = 0; for (uint i = 0; i < _totalEntries; i++) { if (currentOffset == block.TotalSize) { currentBlockIndex += 1; block = _blocks[currentBlockIndex]; currentOffset = 0; } uint id = Unsafe.Read <byte>(block.BasePtr + currentOffset); if (id == 0) { currentBlockIndex += 1; block = _blocks[currentBlockIndex]; currentOffset = 0; id = Unsafe.Read <byte>(block.BasePtr + currentOffset); } Debug.Assert(id != 0); currentOffset += 1; byte *entryBasePtr = block.BasePtr + currentOffset; switch (id) { case BeginEntryID: executor.Begin(); currentOffset += BeginEntrySize; break; case ClearColorTargetID: ref NoAllocClearColorTargetEntry ccte = ref Unsafe.AsRef <NoAllocClearColorTargetEntry>(entryBasePtr); executor.ClearColorTarget(ccte.Index, ccte.ClearColor); currentOffset += ClearColorTargetEntrySize; break; case ClearDepthTargetID: ref NoAllocClearDepthTargetEntry cdte = ref Unsafe.AsRef <NoAllocClearDepthTargetEntry>(entryBasePtr); executor.ClearDepthTarget(cdte.Depth); currentOffset += ClearDepthTargetEntrySize; break; case DrawEntryID: ref NoAllocDrawEntry de = ref Unsafe.AsRef <NoAllocDrawEntry>(entryBasePtr); executor.Draw(de.IndexCount, de.InstanceCount, de.IndexStart, de.VertexOffset, de.InstanceCount); currentOffset += DrawEntrySize; break; case EndEntryID: executor.End(); currentOffset += EndEntrySize; break; case SetFramebufferEntryID: ref NoAllocSetFramebufferEntry sfbe = ref Unsafe.AsRef <NoAllocSetFramebufferEntry>(entryBasePtr); executor.SetFramebuffer(sfbe.Framebuffer); currentOffset += SetFramebufferEntrySize; break; case SetIndexBufferEntryID: ref NoAllocSetIndexBufferEntry sibe = ref Unsafe.AsRef <NoAllocSetIndexBufferEntry>(entryBasePtr); executor.SetIndexBuffer(sibe.IndexBuffer.Item); currentOffset += SetIndexBufferEntrySize; break; case SetPipelineEntryID: ref NoAllocSetPipelineEntry spe = ref Unsafe.AsRef <NoAllocSetPipelineEntry>(entryBasePtr); executor.SetPipeline(spe.Pipeline); currentOffset += SetPipelineEntrySize; break; case SetResourceSetEntryID: ref NoAllocSetResourceSetEntry srse = ref Unsafe.AsRef <NoAllocSetResourceSetEntry>(entryBasePtr); executor.SetResourceSet(srse.Slot, srse.ResourceSet); currentOffset += SetResourceSetEntrySize; break; case SetScissorRectEntryID: ref NoAllocSetScissorRectEntry ssre = ref Unsafe.AsRef <NoAllocSetScissorRectEntry>(entryBasePtr); executor.SetScissorRect(ssre.Index, ssre.X, ssre.Y, ssre.Width, ssre.Height); currentOffset += SetScissorRectEntrySize; break; case SetVertexBufferEntryID: ref NoAllocSetVertexBufferEntry svbe = ref Unsafe.AsRef <NoAllocSetVertexBufferEntry>(entryBasePtr); executor.SetVertexBuffer(svbe.Index, svbe.VertexBuffer.Item); currentOffset += SetVertexBufferEntrySize; break; case SetViewportEntryID: ref NoAllocSetViewportEntry svpe = ref Unsafe.AsRef <NoAllocSetViewportEntry>(entryBasePtr); executor.SetViewport(svpe.Index, ref svpe.Viewport); currentOffset += SetViewportEntrySize; break; case UpdateBufferEntryID: ref NoAllocUpdateBufferEntry ube = ref Unsafe.AsRef <NoAllocUpdateBufferEntry>(entryBasePtr); executor.UpdateBuffer( ube.Buffer.Item, ube.BufferOffsetInBytes, new StagingBlock(ube.StagingBlock.Array, ube.StagingBlock.SizeInBytes, _memoryPool)); currentOffset += UpdateBufferEntrySize; break; case UpdateTextureEntryID: ref NoAllocUpdateTextureEntry ute = ref Unsafe.AsRef <NoAllocUpdateTextureEntry>(entryBasePtr); executor.UpdateTexture( ute.Texture, new StagingBlock(ute.StagingBlock.Array, ute.StagingBlock.SizeInBytes, _memoryPool), ute.X, ute.Y, ute.Z, ute.Width, ute.Height, ute.Depth, ute.MipLevel, ute.ArrayLayer); currentOffset += UpdateTextureEntrySize; break; case UpdateTextureCubeEntryID: ref NoAllocUpdateTextureCubeEntry utce = ref Unsafe.AsRef <NoAllocUpdateTextureCubeEntry>(entryBasePtr); executor.UpdateTextureCube( utce.Texture, new StagingBlock(utce.StagingBlock.Array, utce.StagingBlock.SizeInBytes, _memoryPool), utce.Face, utce.X, utce.Y, utce.Width, utce.Height, utce.MipLevel, utce.ArrayLayer); currentOffset += UpdateTextureCubeEntrySize; break; default: throw new InvalidOperationException("Invalid entry ID: " + id); } } }