public void SetupBuild(int deviceIndex, uint triangleCnt, GpuBuffer vertices, ulong vertices_off, GpuBuffer indices, ulong indices_off, bool shortIndices) { devID = deviceIndex; TrianglePrimitive = new RRTriangleMeshPrimitive() { index_type = shortIndices ? RRIndexType.RrIndexTypeUint16 : RRIndexType.RrIndexTypeUint32, triangle_count = triangleCnt, triangle_indices = indices.GetRayDevicePointer(indices_off), vertex_count = VertexCount, vertex_stride = VertexSize, vertices = vertices.GetRayDevicePointer(vertices_off) }; TrianglePrimitive_ptr = TrianglePrimitive.Pointer(); GeometryBuildInput = new RRGeometryBuildInput() { primitive_type = RRPrimitiveType.RrPrimitiveTypeTriangleMesh, primitive_count = 1, primitives = TrianglePrimitive_ptr, }; GeometryBuildInput_ptr = GeometryBuildInput.Pointer(); RRBuildOptions opts = new RRBuildOptions() { build_flags = 0, backend_specific_info = IntPtr.Zero, }; var opts_ptr = opts.Pointer(); //Allocate the necessary memory ManagedPtr <RRMemoryRequirements> geomMemReqs = new ManagedPtr <RRMemoryRequirements>(); if (rrGetGeometryBuildMemoryRequirements(GraphicsDevice.DeviceInformation[deviceIndex].RaysContext, GeometryBuildInput_ptr, opts_ptr, geomMemReqs) != RRError.RrSuccess) { throw new Exception("Failed to determine geometry memory requirements."); } ScratchBuffer = new GpuBuffer(Name + "_scratch") { MemoryUsage = MemoryUsage.GpuOnly, Size = geomMemReqs.Value.temporary_build_buffer_size, Usage = BufferUsage.Storage | BufferUsage.TransferDst }; ScratchBuffer.Build(deviceIndex); scratchBufferPtr = ScratchBuffer.GetRayDevicePointer(0); BuiltGeometryBuffer = new GpuBuffer(Name + "_geom") { MemoryUsage = MemoryUsage.GpuOnly, Size = geomMemReqs.Value.result_buffer_size, Usage = BufferUsage.Storage | BufferUsage.TransferDst }; BuiltGeometryBuffer.Build(deviceIndex); geomBufferPtr = BuiltGeometryBuffer.GetRayDevicePointer(0); }
public void Build(int deviceIndex) { if (!locked) { var devInfo = GraphicsDevice.GetDeviceInfo(deviceIndex); unsafe { fixed(uint *queueFamInds = devInfo.QueueFamilyIndices) { var creatInfo = new VkImageCreateInfo() { sType = VkStructureType.StructureTypeImageCreateInfo, flags = 0, format = (VkFormat)Format, usage = (VkImageUsageFlags)Usage, mipLevels = Levels, arrayLayers = Layers, extent = new VkExtent3D() { width = Width, height = Height, depth = Depth }, samples = VkSampleCountFlags.SampleCount1Bit, tiling = VkImageTiling.ImageTilingOptimal, sharingMode = VkSharingMode.SharingModeExclusive, initialLayout = (VkImageLayout)InitialLayout, pQueueFamilyIndices = queueFamInds, queueFamilyIndexCount = (uint)devInfo.QueueFamilyIndices.Length, }; creatInfo.imageType = Dimensions switch { 1 => VkImageType.ImageType1d, 2 => VkImageType.ImageType2d, 3 => VkImageType.ImageType3d, _ => throw new Exception("Unknown Image Shape.") }; var vmaCreatInfo = new VmaAllocationCreateInfo() { usage = (VmaMemoryUsage)MemoryUsage }; var allocInfo_p = new ManagedPtr <VmaAllocationInfo>(); var res = GraphicsDevice.CreateImage(deviceIndex, creatInfo.Pointer(), vmaCreatInfo.Pointer(), out var img_l, out var imgAlloc_l, allocInfo_p); hndl = img_l; imgAlloc = imgAlloc_l; allocInfo = allocInfo_p.Value; devID = deviceIndex; CurrentLayout = InitialLayout; CurrentAccesses = AccessFlags.None; CurrentUsageStage = PipelineStage.Top; if (GraphicsDevice.EnableValidation) { var objName = new VkDebugUtilsObjectNameInfoEXT() { sType = VkStructureType.StructureTypeDebugUtilsObjectNameInfoExt, pObjectName = Name, objectType = VkObjectType.ObjectTypeImage, objectHandle = (ulong)hndl }; GraphicsDevice.SetDebugUtilsObjectNameEXT(GraphicsDevice.GetDeviceInfo(deviceIndex).Device, objName.Pointer()); } } } locked = true; } else { throw new Exception("Image is locked."); } }
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; } }
public void Build(int deviceIndex) { if (!locked) { unsafe { //create pipeline shader stages var shaderStages = new VkPipelineShaderStageCreateInfo[Shaders.Length]; var shaderSpecializations = new ManagedPtr <VkSpecializationInfo> [Shaders.Length]; var shaderSpecializationBufferPtrs = new MemoryHandle[Shaders.Length]; for (int i = 0; i < shaderStages.Length; i++) { if (SpecializationData != null) { shaderSpecializationBufferPtrs[i] = SpecializationData[i].Pin(); shaderSpecializations[i] = new VkSpecializationInfo() { mapEntryCount = (uint)SpecializationData[i].Length, pMapEntries = Shaders[i].Specialize(), dataSize = (uint)SpecializationData[i].Length * sizeof(int), pData = (IntPtr)shaderSpecializationBufferPtrs[i].Pointer }.Pointer(); } shaderStages[i].sType = VkStructureType.StructureTypePipelineShaderStageCreateInfo; shaderStages[i].stage = (VkShaderStageFlags)Shaders[i].ShaderType; shaderStages[i].module = Shaders[i].ids[deviceIndex]; shaderStages[i].pName = "main"; shaderStages[i].pSpecializationInfo = shaderSpecializations[i] != null ? shaderSpecializations[i] : IntPtr.Zero; } var shaderStages_ptr = shaderStages.Pointer(); //VkPipelineVertexInputStateCreateInfo - dummy, engine doesn't support fix function vertex input var vertexInputInfo = new VkPipelineVertexInputStateCreateInfo() { sType = VkStructureType.StructureTypePipelineVertexInputStateCreateInfo, vertexBindingDescriptionCount = 0, vertexAttributeDescriptionCount = 0, }; var vertexInputInfo_ptr = vertexInputInfo.Pointer(); //VkPipelineInputAssemblyStateCreateInfo - state var inputAssembly = new VkPipelineInputAssemblyStateCreateInfo() { sType = VkStructureType.StructureTypePipelineInputAssemblyStateCreateInfo, topology = (VkPrimitiveTopology)Topology, primitiveRestartEnable = false, }; var inputAssembly_ptr = inputAssembly.Pointer(); //VkPipelineViewportStateCreateInfo - dynamic state, no scissor var viewport = new VkViewport() { x = ViewportX, y = ViewportY, width = ViewportWidth, height = ViewportHeight, minDepth = ViewportMinDepth, maxDepth = ViewportMaxDepth, }; var scissor = new VkRect2D() { offset = new VkOffset2D() { x = (int)ViewportX, y = (int)ViewportY }, extent = new VkExtent2D() { width = ViewportWidth, height = ViewportHeight } }; var viewport_ptr = viewport.Pointer(); var scissor_ptr = scissor.Pointer(); var viewportCreateInfo = new VkPipelineViewportStateCreateInfo() { sType = VkStructureType.StructureTypePipelineViewportStateCreateInfo, viewportCount = 1, pViewports = viewport_ptr, scissorCount = 1, pScissors = scissor_ptr }; var viewportCreateInfo_ptr = viewportCreateInfo.Pointer(); //VkPipelineRasterizationStateCreateInfo - state var rasterizer = new VkPipelineRasterizationStateCreateInfo() { sType = VkStructureType.StructureTypePipelineRasterizationStateCreateInfo, depthClampEnable = DepthClamp, rasterizerDiscardEnable = RasterizerDiscard, polygonMode = (VkPolygonMode)Fill, lineWidth = LineWidth, cullMode = (VkCullModeFlags)CullMode, frontFace = VkFrontFace.FrontFaceCounterClockwise, //OpenGL default depthBiasEnable = false, depthBiasConstantFactor = 0, depthBiasClamp = 0, depthBiasSlopeFactor = 0, }; var rasterizer_ptr = rasterizer.Pointer(); //VkPipelineMultisampleStateCreateInfo - don't support for now var multisampling = new VkPipelineMultisampleStateCreateInfo() { sType = VkStructureType.StructureTypePipelineMultisampleStateCreateInfo, sampleShadingEnable = false, rasterizationSamples = VkSampleCountFlags.SampleCount1Bit, minSampleShading = 1, pSampleMask = null, alphaToCoverageEnable = false, alphaToOneEnable = false }; var multisampling_ptr = multisampling.Pointer(); //VkPipelineDepthStencilStateCreateInfo - state var depthStencil = new VkPipelineDepthStencilStateCreateInfo() { sType = VkStructureType.StructureTypePipelineDepthStencilStateCreateInfo, depthTestEnable = true, depthCompareOp = (VkCompareOp)DepthTest, depthWriteEnable = DepthWrite, depthBoundsTestEnable = false, stencilTestEnable = false, maxDepthBounds = ViewportMaxDepth, minDepthBounds = ViewportMinDepth, }; var depthStencil_ptr = depthStencil.Pointer(); //VkPipelineColorBlendStateCreateInfo - state var colorBlendStates = new VkPipelineColorBlendAttachmentState[RenderPass.ColorAttachments == null ? 0 : RenderPass.ColorAttachments.Length]; for (int i = 0; i < colorBlendStates.Length; i++) { colorBlendStates[i] = new VkPipelineColorBlendAttachmentState() { colorWriteMask = VkColorComponentFlags.ColorComponentRBit | VkColorComponentFlags.ColorComponentGBit | VkColorComponentFlags.ColorComponentBBit | VkColorComponentFlags.ColorComponentABit, blendEnable = false, }; } var colorBlendStates_ptr = colorBlendStates.Pointer(); var colorBlend = new VkPipelineColorBlendStateCreateInfo() { sType = VkStructureType.StructureTypePipelineColorBlendStateCreateInfo, logicOpEnable = false, logicOp = VkLogicOp.LogicOpCopy, attachmentCount = (uint)colorBlendStates.Length, pAttachments = colorBlendStates_ptr, }; colorBlend.blendConstants[0] = 0; colorBlend.blendConstants[1] = 0; colorBlend.blendConstants[2] = 0; colorBlend.blendConstants[3] = 0; var colorBlend_ptr = colorBlend.Pointer(); var dynamicStates = stackalloc VkDynamicState[] { VkDynamicState.DynamicStateViewport }; var dynamicState = new VkPipelineDynamicStateCreateInfo() { sType = VkStructureType.StructureTypePipelineDynamicStateCreateInfo, dynamicStateCount = ViewportDynamic ? 1u : 0u, pDynamicStates = dynamicStates }; var dynamicState_ptr = dynamicState.Pointer(); //Setup graphics pipeline var pipelineInfo = new VkGraphicsPipelineCreateInfo() { sType = VkStructureType.StructureTypeGraphicsPipelineCreateInfo, stageCount = (uint)shaderStages.Length, pStages = shaderStages_ptr, pVertexInputState = vertexInputInfo_ptr, pInputAssemblyState = inputAssembly_ptr, pViewportState = viewportCreateInfo_ptr, pRasterizationState = rasterizer_ptr, pMultisampleState = multisampling_ptr, pDepthStencilState = depthStencil_ptr, pColorBlendState = colorBlend_ptr, pDynamicState = dynamicState_ptr, layout = PipelineLayout.hndl, renderPass = RenderPass.hndl, subpass = 0, basePipelineHandle = IntPtr.Zero, basePipelineIndex = -1, }; IntPtr pipeline_l = IntPtr.Zero; if (vkCreateGraphicsPipelines(GraphicsDevice.GetDeviceInfo(deviceIndex).Device, IntPtr.Zero, 1, pipelineInfo.Pointer(), null, &pipeline_l) != VkResult.Success) { throw new Exception("Failed to create graphics pipeline."); } hndl = pipeline_l; if (GraphicsDevice.EnableValidation) { var objName = new VkDebugUtilsObjectNameInfoEXT() { sType = VkStructureType.StructureTypeDebugUtilsObjectNameInfoExt, pObjectName = Name, objectType = VkObjectType.ObjectTypePipeline, objectHandle = (ulong)hndl }; GraphicsDevice.SetDebugUtilsObjectNameEXT(GraphicsDevice.GetDeviceInfo(deviceIndex).Device, objName.Pointer()); } devID = deviceIndex; locked = true; } } else { throw new Exception("Pipeline is locked."); } }
private static uint RateDevice(IntPtr physDevice) { var devProps = new ManagedPtr <VkPhysicalDeviceProperties>(); var devFeats = new ManagedPtr <VkPhysicalDeviceFeatures>(); vkGetPhysicalDeviceProperties(physDevice, devProps); vkGetPhysicalDeviceFeatures(physDevice, devFeats); var devProps_ = devProps.Value; var devFeats_ = devFeats.Value; uint score = 0; if (devProps_.deviceType == VkPhysicalDeviceType.PhysicalDeviceTypeDiscreteGpu) { score += 100; } score += devProps_.limits.maxImageDimension2D; if (!devFeats_.multiDrawIndirect) { return(0); } if (!devFeats_.tessellationShader) { return(0); } if (!ExtensionsSupported(physDevice)) { return(0); } var caps_ptr = new ManagedPtr <VkSurfaceCapabilitiesKHR>(); vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physDevice, surfaceHndl, caps_ptr); var caps = caps_ptr.Value; uint fmt_cnt = 0; vkGetPhysicalDeviceSurfaceFormatsKHR(physDevice, surfaceHndl, &fmt_cnt, null); var fmts_ptr = new ManagedPtrArray <VkSurfaceFormatKHR>(fmt_cnt); vkGetPhysicalDeviceSurfaceFormatsKHR(physDevice, surfaceHndl, &fmt_cnt, fmts_ptr); var fmts = fmts_ptr.Value; bool fmt_valid = false; VkSurfaceFormatKHR chosen_fmt = new VkSurfaceFormatKHR(); foreach (var avail_fmt in fmts) { if (avail_fmt.format == VkFormat.FormatB8g8r8a8Unorm && avail_fmt.colorSpace == VkColorSpaceKHR.ColorSpaceSrgbNonlinearKhr) { chosen_fmt = avail_fmt; fmt_valid = true; break; } } if (!fmt_valid && fmts.Length > 0) { chosen_fmt = fmts[0]; fmt_valid = true; } uint present_mode_cnt = 0; vkGetPhysicalDeviceSurfacePresentModesKHR(physDevice, surfaceHndl, &present_mode_cnt, null); var present_modes = stackalloc VkPresentModeKHR[(int)present_mode_cnt]; vkGetPhysicalDeviceSurfacePresentModesKHR(physDevice, surfaceHndl, &present_mode_cnt, present_modes); bool present_valid = false; VkPresentModeKHR chosen_present = VkPresentModeKHR.PresentModeBeginRangeKhr; for (int i = 0; i < present_mode_cnt; i++) { var avail_present = present_modes[i]; if (avail_present == VkPresentModeKHR.PresentModeMailboxKhr) { present_valid = true; chosen_present = VkPresentModeKHR.PresentModeMailboxKhr; } else if (avail_present == VkPresentModeKHR.PresentModeFifoRelaxedKhr) { present_valid = true; chosen_present = VkPresentModeKHR.PresentModeFifoRelaxedKhr; } } if (!present_valid) { present_valid = true; chosen_present = VkPresentModeKHR.PresentModeFifoKhr; } chosen_present = VkPresentModeKHR.PresentModeImmediateKhr; if (!fmt_valid) { return(0); } if (!present_valid) { return(0); } present_mode = chosen_present; surface_fmt = chosen_fmt; return(score); }