public void SubmitCommandBuffer(CommandBuffer buffer, GpuSemaphore[] waitSems, GpuSemaphore[] signalSems, Fence fence) { if (buffer.IsEmpty) { throw new Exception(); } unsafe { /*if (buffer.IsRadRayStream) * { * if (waitSems != null && waitSems.Length > 0) * throw new Exception(); * if (signalSems != null && signalSems.Length > 0) * throw new Exception(); * if (fence != null) * throw new Exception(); * * IntPtr wait_event = IntPtr.Zero; * rrSumbitCommandStream(GraphicsDevice.DeviceInformation[DeviceIndex].RaysContext, buffer.radRayStream, IntPtr.Zero, &wait_event); * rrWaitEvent(GraphicsDevice.DeviceInformation[DeviceIndex].RaysContext, wait_event); * rrReleaseEvent(GraphicsDevice.DeviceInformation[DeviceIndex].RaysContext, wait_event); * } * else*/ { var waitSemaphores = stackalloc IntPtr[waitSems == null ? 0 : waitSems.Length]; var signalSemaphores = stackalloc IntPtr[signalSems == null ? 0 : signalSems.Length]; var waitSemaphoreVals = stackalloc ulong[waitSems == null ? 0 : waitSems.Length]; var signalSemaphoreVals = stackalloc ulong[signalSems == null ? 0 : signalSems.Length]; bool hasTimeline = false; for (int i = 0; i < (waitSems == null ? 0 : waitSems.Length); i++) { waitSemaphoreVals[i] = waitSems[i].timeline ? GraphicsDevice.CurrentFrameCount : 1; waitSemaphores[i] = waitSems[i].hndl; if (waitSems[i].Name == "Semaphore_1_5") { Console.WriteLine($"{buffer.Name}: WAIT SEM"); } if (waitSems[i].timeline) { hasTimeline = true; } } for (int i = 0; i < (signalSems == null ? 0 : signalSems.Length); i++) { signalSemaphoreVals[i] = signalSems[i].timeline ? GraphicsDevice.CurrentFrameCount + 1 : 0; signalSemaphores[i] = signalSems[i].hndl; if (signalSems[i].Name == "Semaphore_1_5") { Console.WriteLine($"{buffer.Name}: SIGNAL SEM"); } if (signalSems[i].timeline) { hasTimeline = true; } } var waitStages = stackalloc VkPipelineStageFlags[waitSems == null ? 0 : waitSems.Length]; var cmdBuffers = stackalloc IntPtr[] { buffer.hndl }; for (int i = 0; i < (waitSems == null ? 0 : waitSems.Length); i++) { waitStages[i] = VkPipelineStageFlags.PipelineStageColorAttachmentOutputBit; } var timelineSems = new VkTimelineSemaphoreSubmitInfo() { sType = VkStructureType.StructureTypeTimelineSemaphoreSubmitInfo, signalSemaphoreValueCount = signalSems == null ? 0 : (uint)signalSems.Length, waitSemaphoreValueCount = waitSems == null ? 0 : (uint)waitSems.Length, pSignalSemaphoreValues = signalSemaphoreVals, pWaitSemaphoreValues = waitSemaphoreVals }; var timelineSems_ptr = timelineSems.Pointer(); var submitInfo = new VkSubmitInfo() { sType = VkStructureType.StructureTypeSubmitInfo, waitSemaphoreCount = waitSems == null ? 0 : (uint)waitSems.Length, pWaitSemaphores = waitSemaphores, pWaitDstStageMask = waitStages, commandBufferCount = 1, pCommandBuffers = cmdBuffers, signalSemaphoreCount = signalSems == null ? 0 : (uint)signalSems.Length, pSignalSemaphores = signalSemaphores, pNext = hasTimeline ? timelineSems_ptr : IntPtr.Zero }; var ptr = submitInfo.Pointer(); var res = vkQueueSubmit(Handle, 1, ptr, fence == null ? IntPtr.Zero : fence.hndl); if (res != VkResult.Success) { throw new Exception("Failed to submit command buffer."); } } } }
//texture upload public void UploadTexture(GpuBuffer buffer, Texture tex, int write_lv, Vector3 offset, Vector3 size, PixelFormat fmt, PixelType type, Fence f) { Commands.Add(new CommandEntry() { Type = CommandType.TexUpload, SyncFence = f, Buffer = buffer, Texture = tex, WriteLevel = write_lv, Offset = offset, Size = size, Format = fmt, PixType = type }); }
public static void Init() { optionalExtn_avail = new bool[optionalDeviceExtns.Length]; Console.BackgroundColor = ConsoleColor.Black; Console.ForegroundColor = ConsoleColor.White; Window = new GameWindow(AppName); fixed(IntPtr *instancePtr = &instanceHndl) fixed(IntPtr * surfacePtr = &surfaceHndl) { VkResult res; var instLayers = new List <string>(); var instExtns = new List <string>(); var devExtns = new List <string>(); uint glfwExtnCnt = 0; var glfwExtns = glfwGetRequiredInstanceExtensions(&glfwExtnCnt); for (int i = 0; i < glfwExtnCnt; i++) { instExtns.Add(Marshal.PtrToStringAnsi(glfwExtns[i])); } instExtns.Add(VkKhrGetPhysicalDeviceProperties2ExtensionName); if (EnableValidation) { instLayers.Add("VK_LAYER_KHRONOS_validation"); instExtns.Add(VkExtDebugUtilsExtensionName); } var layers = stackalloc IntPtr[instLayers.Count]; for (int i = 0; i < instLayers.Count; i++) { layers[i] = Marshal.StringToHGlobalAnsi(instLayers[i]); } var extns = stackalloc IntPtr[instExtns.Count]; for (int i = 0; i < instExtns.Count; i++) { extns[i] = Marshal.StringToHGlobalAnsi(instExtns[i]); } { var appInfo = new VkApplicationInfo() { sType = VkStructureType.StructureTypeApplicationInfo, pApplicationName = AppName, pEngineName = EngineName, apiVersion = VkApiVersion12, applicationVersion = 1, engineVersion = 1, pNext = IntPtr.Zero }; var appInfo_ptr = appInfo.Pointer(); var instCreatInfo = new VkInstanceCreateInfo() { sType = VkStructureType.StructureTypeInstanceCreateInfo, pApplicationInfo = appInfo_ptr, }; instCreatInfo.ppEnabledLayerNames = layers; instCreatInfo.enabledLayerCount = (uint)instLayers.Count; instCreatInfo.ppEnabledExtensionNames = extns; instCreatInfo.enabledExtensionCount = (uint)instExtns.Count; var instCreatInfo_ptr = instCreatInfo.Pointer(); //register instance create debug message handler debugCreatInfo = new VkDebugUtilsMessengerCreateInfoEXT() { sType = VkStructureType.StructureTypeDebugUtilsMessengerCreateInfoExt, messageSeverity = VkDebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityErrorBitExt | VkDebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityWarningBitExt | VkDebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityVerboseBitExt | VkDebugUtilsMessageSeverityFlagsEXT.DebugUtilsMessageSeverityInfoBitExt, messageType = VkDebugUtilsMessageTypeFlagsEXT.DebugUtilsMessageTypeGeneralBitExt | VkDebugUtilsMessageTypeFlagsEXT.DebugUtilsMessageTypePerformanceBitExt | VkDebugUtilsMessageTypeFlagsEXT.DebugUtilsMessageTypeValidationBitExt, pfnUserCallback = DebugCallback }; var debugCreatInfo_ptr = debugCreatInfo.Pointer(); if (EnableValidation) { instCreatInfo.pNext = debugCreatInfo_ptr; } res = vkCreateInstance(instCreatInfo_ptr, null, instancePtr); if (res != VkResult.Success) { throw new Exception("Failed to create instance."); } } if (EnableValidation) { SetupDebugMessengers(instanceHndl); var debugCreatInfo_ptr = debugCreatInfo.Pointer(); fixed(IntPtr *dbg_ptr = &debugMessenger) res = CreateDebugUtilsMessengerEXT(instanceHndl, debugCreatInfo_ptr, IntPtr.Zero, dbg_ptr); if (res != VkResult.Success) { throw new Exception("Failed to register debug callback."); } } res = Window.CreateSurface(instanceHndl, surfacePtr); if (res != VkResult.Success) { throw new Exception("Failed to create surface."); } uint devCount = 0; vkEnumeratePhysicalDevices(instanceHndl, &devCount, null); if (devCount == 0) { throw new Exception("Failed to find Vulkan compatible devices."); } var devices = new IntPtr[devCount]; fixed(IntPtr *devicesPtr = devices) vkEnumeratePhysicalDevices(instanceHndl, &devCount, devicesPtr); var ratedDevices = new List <(uint, IntPtr)>(); for (int i = 0; i < devices.Length; i++) { //rate each device ratedDevices.Add((RateDevice(devices[i]), devices[i])); } var orderedDevices = ratedDevices.OrderByDescending(a => a.Item1) .Select(a => a.Item2) .ToArray(); DeviceInformation = new DeviceInfo[orderedDevices.Length]; DeviceInformation[0] = new DeviceInfo() { PhysicalDevice = orderedDevices[0] }; //TODO for now just choose the first device { //allocate queues for primary device uint graphicsFamily = ~0u; uint computeFamily = ~0u; uint transferFamily = ~0u; uint presentFamily = ~0u; uint qfam_cnt = 0; vkGetPhysicalDeviceQueueFamilyProperties(orderedDevices[0], &qfam_cnt, null); var qFams_ptr = new ManagedPtrArray <VkQueueFamilyProperties>(qfam_cnt); vkGetPhysicalDeviceQueueFamilyProperties(orderedDevices[0], &qfam_cnt, qFams_ptr); var qFams = qFams_ptr.Value; uint qFamIdx = 0; foreach (var qFam in qFams) { bool presentSupport = false; vkGetPhysicalDeviceSurfaceSupportKHR(orderedDevices[0], qFamIdx, surfaceHndl, &presentSupport); if ((qFam.queueFlags & VkQueueFlags.QueueGraphicsBit) != 0 && graphicsFamily == ~0u) { graphicsFamily = qFamIdx; if (presentSupport) { presentFamily = qFamIdx; } qFamIdx++; continue; } if ((qFam.queueFlags & VkQueueFlags.QueueComputeBit) != 0 && computeFamily == ~0u) { computeFamily = qFamIdx; if ((qFam.queueFlags & VkQueueFlags.QueueTransferBit) != 0) { transferFamily = qFamIdx; } qFamIdx++; continue; } if ((qFam.queueFlags & VkQueueFlags.QueueTransferBit) != 0) { transferFamily = qFamIdx; } if (graphicsFamily != ~0u && computeFamily != ~0u && transferFamily != ~0u && presentFamily != ~0u) { break; } qFamIdx++; } if (presentFamily == ~0u) { throw new Exception("Separate present queue support hasn't been implemented."); } var max_q_priority = stackalloc float[] { 1.0f }; var dual_graph_q_priority = stackalloc float[] { 1.0f }; var triple_graph_q_priority = stackalloc float[] { 1.0f, 1.0f, 1.0f }; VkDeviceQueueCreateInfo graphics_qCreatInfo = new VkDeviceQueueCreateInfo() { sType = VkStructureType.StructureTypeDeviceQueueCreateInfo, queueFamilyIndex = graphicsFamily, queueCount = 1, pQueuePriorities = max_q_priority }; VkDeviceQueueCreateInfo compute_qCreatInfo = new VkDeviceQueueCreateInfo { sType = VkStructureType.StructureTypeDeviceQueueCreateInfo, queueFamilyIndex = computeFamily, queueCount = 1, pQueuePriorities = max_q_priority }; VkDeviceQueueCreateInfo transfer_qCreatInfo = new VkDeviceQueueCreateInfo(); if (transferFamily != graphicsFamily) { transfer_qCreatInfo.sType = VkStructureType.StructureTypeDeviceQueueCreateInfo; transfer_qCreatInfo.queueFamilyIndex = transferFamily; transfer_qCreatInfo.queueCount = 1; transfer_qCreatInfo.pQueuePriorities = max_q_priority; } else { graphics_qCreatInfo.queueCount = 2; graphics_qCreatInfo.pQueuePriorities = dual_graph_q_priority; } var qCreatInfos = new VkDeviceQueueCreateInfo[3]; qCreatInfos[0] = graphics_qCreatInfo; qCreatInfos[1] = compute_qCreatInfo; if (transferFamily != graphicsFamily) { qCreatInfos[2] = transfer_qCreatInfo; } DeviceInformation[0].GraphicsFamily = graphicsFamily; DeviceInformation[0].ComputeFamily = computeFamily; DeviceInformation[0].TransferFamily = transferFamily; DeviceInformation[0].PresentFamily = presentFamily; VkPhysicalDeviceFeatures devFeats = new VkPhysicalDeviceFeatures() { multiDrawIndirect = true, drawIndirectFirstInstance = true, fullDrawIndexUint32 = true, tessellationShader = true, fragmentStoresAndAtomics = true, vertexPipelineStoresAndAtomics = true, robustBufferAccess = EnableValidation, shaderInt16 = true, samplerAnisotropy = true, fillModeNonSolid = true, largePoints = true, }; var devFeats11 = new VkPhysicalDeviceVulkan11Features() { sType = VkStructureType.StructureTypePhysicalDeviceVulkan11Features, shaderDrawParameters = true, //storageBuffer16BitAccess = true, //uniformAndStorageBuffer16BitAccess = true, //storagePushConstant16 = true, }; var devFeats11_ptr = devFeats11.Pointer(); /* * var depthStenc = new VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures() * { * sType = VkStructureType.StructureTypePhysicalDeviceSeparateDepthStencilLayoutsFeatures, * separateDepthStencilLayouts = true, * pNext = devFeats11_ptr * }; * var depthStenc_ptr = depthStenc.Pointer(); * * var timelineSems = new VkPhysicalDeviceTimelineSemaphoreFeatures() * { * sType = VkStructureType.StructureTypePhysicalDeviceTimelineSemaphoreFeatures, * timelineSemaphore = true, * pNext = depthStenc_ptr, * }; * var timelineSems_ptr = timelineSems.Pointer(); * * var indirectCnt = new VkPhysicalDeviceShaderFloat16Int8Features() * { * sType = VkStructureType.StructureTypePhysicalDeviceShaderFloat16Int8Features, * shaderFloat16 = true, * shaderInt8 = true, * pNext = timelineSems_ptr, * }; * var indirectCnt_ptr = indirectCnt.Pointer(); * * var uboLayout = new VkPhysicalDeviceUniformBufferStandardLayoutFeatures() * { * sType = VkStructureType.StructureTypePhysicalDeviceUniformBufferStandardLayoutFeatures, * uniformBufferStandardLayout = true, * pNext = indirectCnt_ptr * }; * var uboLayout_ptr = uboLayout.Pointer(); * * var storageByte = new VkPhysicalDevice8BitStorageFeatures() * { * sType = VkStructureType.StructureTypePhysicalDevice8bitStorageFeatures, * storageBuffer8BitAccess = true, * uniformAndStorageBuffer8BitAccess = true, * pNext = uboLayout_ptr * }; * var storageByte_ptr = storageByte.Pointer(); * var descIndexing = new VkPhysicalDeviceDescriptorIndexingFeatures() * { * sType = VkStructureType.StructureTypePhysicalDeviceDescriptorIndexingFeatures, * descriptorBindingSampledImageUpdateAfterBind = true, * descriptorBindingStorageBufferUpdateAfterBind = true, * descriptorBindingStorageImageUpdateAfterBind = true, * descriptorBindingStorageTexelBufferUpdateAfterBind = true, * descriptorBindingUniformBufferUpdateAfterBind = true, * descriptorBindingUniformTexelBufferUpdateAfterBind = true, * descriptorBindingUpdateUnusedWhilePending = true, * descriptorBindingPartiallyBound = true, * shaderStorageTexelBufferArrayDynamicIndexing = true, * pNext = storageByte_ptr, * }; * var descIndexing_ptr = descIndexing.Pointer();*/ //var drawIndirectCount = new VkDrawIndirecCount var devFeats12 = new VkPhysicalDeviceVulkan12Features() { sType = VkStructureType.StructureTypePhysicalDeviceVulkan12Features, separateDepthStencilLayouts = true, timelineSemaphore = true, drawIndirectCount = true, shaderFloat16 = true, shaderInt8 = true, uniformBufferStandardLayout = true, storageBuffer8BitAccess = true, uniformAndStorageBuffer8BitAccess = true, descriptorIndexing = true, descriptorBindingSampledImageUpdateAfterBind = true, descriptorBindingStorageBufferUpdateAfterBind = true, descriptorBindingStorageImageUpdateAfterBind = true, descriptorBindingStorageTexelBufferUpdateAfterBind = true, descriptorBindingUniformBufferUpdateAfterBind = true, descriptorBindingUniformTexelBufferUpdateAfterBind = true, descriptorBindingUpdateUnusedWhilePending = true, descriptorBindingPartiallyBound = true, shaderStorageTexelBufferArrayDynamicIndexing = true, shaderStorageBufferArrayNonUniformIndexing = true, runtimeDescriptorArray = true, descriptorBindingVariableDescriptorCount = true, pNext = devFeats11_ptr }; var devFeats12_ptr = devFeats12.Pointer(); devExtns.AddRange(requiredDeviceExtns); for (int i = 0; i < optionalExtn_avail.Length; i++) { if (optionalExtn_avail[i]) { devExtns.Add(optionalDeviceExtns[i]); } } var devExtns_ptr = stackalloc IntPtr[devExtns.Count]; for (int i = 0; i < devExtns.Count; i++) { devExtns_ptr[i] = Marshal.StringToHGlobalAnsi(devExtns[i]); } var qCreatInfos_ptr = qCreatInfos.Pointer(); var devFeats_ptr = devFeats.Pointer(); var devCreatInfo = new VkDeviceCreateInfo() { sType = VkStructureType.StructureTypeDeviceCreateInfo, queueCreateInfoCount = (uint)(transferFamily != graphicsFamily ? 3 : 2), enabledExtensionCount = (uint)devExtns.Count, ppEnabledExtensionNames = devExtns_ptr, enabledLayerCount = (uint)instLayers.Count, ppEnabledLayerNames = layers, pEnabledFeatures = devFeats_ptr, pQueueCreateInfos = qCreatInfos_ptr, pNext = devFeats12_ptr }; var devCreatInfo_ptr = devCreatInfo.Pointer(); IntPtr deviceHndl = IntPtr.Zero; res = vkCreateDevice(orderedDevices[0], devCreatInfo_ptr, null, &deviceHndl); if (res != VkResult.Success) { throw new Exception("Failed to create logical device."); } DeviceInformation[0].Device = deviceHndl; //Setup memory allocator var allocCreatInfo = new VmaAllocatorCreateInfo() { physicalDevice = DeviceInformation[0].PhysicalDevice, device = DeviceInformation[0].Device }; var allocCreatInfo_ptr = allocCreatInfo.Pointer(); fixed(IntPtr *vma_alloc_ptr = &DeviceInformation[0].vmaAllocator) res = vmaCreateAllocator(allocCreatInfo_ptr, vma_alloc_ptr); if (res != VkResult.Success) { throw new Exception("Failed to initialize allocator."); } IntPtr graph_q_hndl = IntPtr.Zero; IntPtr trans_q_hndl = IntPtr.Zero; IntPtr comp_q_hndl = IntPtr.Zero; vkGetDeviceQueue(DeviceInformation[0].Device, graphicsFamily, 0, &graph_q_hndl); vkGetDeviceQueue(DeviceInformation[0].Device, computeFamily, 0, &comp_q_hndl); if (transferFamily != graphicsFamily) { vkGetDeviceQueue(DeviceInformation[0].Device, transferFamily, 0, &trans_q_hndl); } else { vkGetDeviceQueue(DeviceInformation[0].Device, graphicsFamily, 1, &trans_q_hndl); } DeviceInformation[0].GraphicsQueue = new GpuQueue(CommandQueueKind.Graphics, graph_q_hndl, graphicsFamily, 0); DeviceInformation[0].TransferQueue = new GpuQueue(CommandQueueKind.Transfer, trans_q_hndl, transferFamily, 0); DeviceInformation[0].ComputeQueue = new GpuQueue(CommandQueueKind.Compute, comp_q_hndl, computeFamily, 0); var queue_indices = new List <uint>(); if (!queue_indices.Contains(DeviceInformation[0].GraphicsFamily)) { queue_indices.Add(DeviceInformation[0].GraphicsFamily); } if (!queue_indices.Contains(DeviceInformation[0].ComputeFamily)) { queue_indices.Add(DeviceInformation[0].ComputeFamily); } if (!queue_indices.Contains(DeviceInformation[0].PresentFamily)) { queue_indices.Add(DeviceInformation[0].PresentFamily); } if (!queue_indices.Contains(DeviceInformation[0].TransferFamily)) { queue_indices.Add(DeviceInformation[0].TransferFamily); } DeviceInformation[0].QueueFamilyIndices = queue_indices.ToArray(); var physDeviceProps = new ManagedPtr <VkPhysicalDeviceProperties>(); vkGetPhysicalDeviceProperties(DeviceInformation[0].PhysicalDevice, physDeviceProps); DeviceInformation[0].Properties = physDeviceProps.Value; var caps_ptr = new ManagedPtr <VkSurfaceCapabilitiesKHR>(); vkGetPhysicalDeviceSurfaceCapabilitiesKHR(DeviceInformation[0].PhysicalDevice, surfaceHndl, caps_ptr); var caps = caps_ptr.Value; VkExtent2D cur_extent = new VkExtent2D(); if (caps.currentExtent.width != uint.MaxValue) { cur_extent = caps.currentExtent; } else { cur_extent.width = System.Math.Clamp((uint)Window.Width, caps.minImageExtent.width, caps.maxImageExtent.width); cur_extent.height = System.Math.Clamp((uint)Window.Height, caps.minImageExtent.height, caps.maxImageExtent.height); } uint img_cnt = caps.minImageCount + 1; VkSwapchainCreateInfoKHR swapCreatInfo = new VkSwapchainCreateInfoKHR() { sType = VkStructureType.StructureTypeSwapchainCreateInfoKhr, surface = surfaceHndl, minImageCount = img_cnt, imageFormat = surface_fmt.format, imageColorSpace = surface_fmt.colorSpace, imageExtent = cur_extent, imageArrayLayers = 1, imageUsage = VkImageUsageFlags.ImageUsageColorAttachmentBit | VkImageUsageFlags.ImageUsageTransferDstBit | VkImageUsageFlags.ImageUsageTransferSrcBit, imageSharingMode = VkSharingMode.SharingModeExclusive, queueFamilyIndexCount = 0, pQueueFamilyIndices = null, preTransform = caps.currentTransform, compositeAlpha = VkCompositeAlphaFlagsKHR.CompositeAlphaOpaqueBitKhr, presentMode = present_mode, clipped = true, oldSwapchain = IntPtr.Zero }; var swapCreatInfo_ptr = swapCreatInfo.Pointer(); fixed(IntPtr *swapchain_ptr = &swapChainHndl) res = vkCreateSwapchainKHR(DeviceInformation[0].Device, swapCreatInfo_ptr, null, swapchain_ptr); if (res != VkResult.Success) throw new Exception("Failed to create swapchain."); fixed(uint *swapchain_img_cnt_ptr = &swapchain_img_cnt) { vkGetSwapchainImagesKHR(DeviceInformation[0].Device, swapChainHndl, swapchain_img_cnt_ptr, null); var swapchainImages_l = new IntPtr[swapchain_img_cnt]; fixed(IntPtr *swapchain_imgs = swapchainImages_l) vkGetSwapchainImagesKHR(DeviceInformation[0].Device, swapChainHndl, swapchain_img_cnt_ptr, swapchain_imgs); MaxFramesInFlight = swapchain_img_cnt; MaxFrameCount = swapchain_img_cnt; swapchainImages = new Image[swapchain_img_cnt]; for (int i = 0; i < swapchainImages.Length; i++) { swapchainImages[i] = new Image($"Swapchain_{i}") { Dimensions = 2, Width = cur_extent.width, Height = cur_extent.height, Depth = 1, Format = (ImageFormat)surface_fmt.format, Layers = 1, Levels = 1, MemoryUsage = MemoryUsage.GpuOnly, Usage = ImageUsage.Sampled, InitialLayout = ImageLayout.Undefined, Cubemappable = false, }; swapchainImages[i].Build(0, swapchainImages_l[i]); } surface_extent = cur_extent; swapchainViews = new ImageView[swapchain_img_cnt]; DefaultFramebuffer = new Framebuffer[swapchain_img_cnt]; for (int i = 0; i < swapchainImages.Length; i++) { swapchainViews[i] = new ImageView($"Swapchain_{i}") { BaseLayer = 0, BaseLevel = 0, Format = (ImageFormat)surface_fmt.format, LayerCount = 1, LevelCount = 1, ViewType = ImageViewType.View2D, }; swapchainViews[i].Build(swapchainImages[i]); DefaultFramebuffer[i] = new Framebuffer(); DefaultFramebuffer[i].Width = surface_extent.width; DefaultFramebuffer[i].Height = surface_extent.height; DefaultFramebuffer[i].Name = $"Swapchain_{i}"; DefaultFramebuffer[i].ColorAttachments = new ImageView[] { swapchainViews[i] }; } } for (int i = 0; i < instLayers.Count; i++) { Marshal.FreeHGlobal(layers[i]); } for (int i = 0; i < instExtns.Count; i++) { Marshal.FreeHGlobal(extns[i]); } for (int i = 0; i < devExtns.Count; i++) { Marshal.FreeHGlobal(devExtns_ptr[i]); } //TODO allocate compute and trasnfer queues for all secondary devices } for (int i = 0; i < 1 /*DeviceInformation.Length*/; i++) { var devInfo = DeviceInformation[i]; IntPtr rrCtxtHndl = IntPtr.Zero; if (rrCreateContextVk(RrApiVersion, devInfo.Device, devInfo.PhysicalDevice, devInfo.ComputeQueue.Handle, devInfo.ComputeFamily, &rrCtxtHndl) != RRError.RrSuccess) { Console.WriteLine($"Failed to initialize RadeonRays for device #{i}."); } DeviceInformation[i].RaysContext = rrCtxtHndl; } FrameFinishedSemaphore = new GpuSemaphore[MaxFramesInFlight]; ImageAvailableSemaphore = new GpuSemaphore[MaxFramesInFlight]; InflightFences = new Fence[MaxFramesInFlight]; for (int i = 0; i < MaxFramesInFlight; i++) { FrameFinishedSemaphore[i] = new GpuSemaphore(); FrameFinishedSemaphore[i].Build(0, false, 0); ImageAvailableSemaphore[i] = new GpuSemaphore(); ImageAvailableSemaphore[i].Build(0, false, 0); InflightFences[i] = new Fence { CreateSignaled = true }; InflightFences[i].Build(0); } Width = (uint)Window.Width; Height = (uint)Window.Height; } }