/// <summary> /// Initializes the specified device. /// </summary> /// <param name="graphicsProfiles">The graphics profiles.</param> /// <param name="deviceCreationFlags">The device creation flags.</param> /// <param name="windowHandle">The window handle.</param> private void InitializePlatformDevice(GraphicsProfile[] graphicsProfiles, DeviceCreationFlags deviceCreationFlags, object windowHandle) { if (nativeDevice != null) { // Destroy previous device ReleaseDevice(); } rendererName = Adapter.NativeAdapter.Description.Description; // Profiling is supported through pix markers IsProfilingSupported = true; // Command lists are thread-safe and execute deferred IsDeferred = true; bool isDebug = (deviceCreationFlags & DeviceCreationFlags.Debug) != 0; if (isDebug) { SharpDX.Direct3D12.DebugInterface.Get().EnableDebugLayer(); } // Default fallback if (graphicsProfiles.Length == 0) { graphicsProfiles = new[] { GraphicsProfile.Level_11_0 } } ; // Create Device D3D12 with feature Level based on profile for (int index = 0; index < graphicsProfiles.Length; index++) { var graphicsProfile = graphicsProfiles[index]; try { // D3D12 supports only feature level 11+ var level = graphicsProfile.ToFeatureLevel(); if (level < SharpDX.Direct3D.FeatureLevel.Level_11_0) { level = SharpDX.Direct3D.FeatureLevel.Level_11_0; } nativeDevice = new SharpDX.Direct3D12.Device(Adapter.NativeAdapter, level); RequestedProfile = graphicsProfile; CurrentFeatureLevel = level; break; } catch (Exception) { if (index == graphicsProfiles.Length - 1) { throw; } } } // Describe and create the command queue. var queueDesc = new SharpDX.Direct3D12.CommandQueueDescription(SharpDX.Direct3D12.CommandListType.Direct); NativeCommandQueue = nativeDevice.CreateCommandQueue(queueDesc); //queueDesc.Type = CommandListType.Copy; NativeCopyCommandQueue = nativeDevice.CreateCommandQueue(queueDesc); TimestampFrequency = NativeCommandQueue.TimestampFrequency; SrvHandleIncrementSize = NativeDevice.GetDescriptorHandleIncrementSize(DescriptorHeapType.ConstantBufferViewShaderResourceViewUnorderedAccessView); SamplerHandleIncrementSize = NativeDevice.GetDescriptorHandleIncrementSize(DescriptorHeapType.Sampler); if (isDebug) { var debugDevice = nativeDevice.QueryInterfaceOrNull <DebugDevice>(); if (debugDevice != null) { var infoQueue = debugDevice.QueryInterfaceOrNull <InfoQueue>(); if (infoQueue != null) { MessageId[] disabledMessages = { // This happens when render target or depth stencil clear value is diffrent // than provided during resource allocation. MessageId.CleardepthstencilviewMismatchingclearvalue, MessageId.ClearrendertargetviewMismatchingclearvalue, // This occurs when there are uninitialized descriptors in a descriptor table, // even when a shader does not access the missing descriptors. MessageId.InvalidDescriptorHandle, // These happen when capturing with VS diagnostics MessageId.MapInvalidNullRange, MessageId.UnmapInvalidNullRange, }; // Disable irrelevant debug layer warnings InfoQueueFilter filter = new InfoQueueFilter { DenyList = new InfoQueueFilterDescription { Ids = disabledMessages } }; infoQueue.AddStorageFilterEntries(filter); //infoQueue.SetBreakOnSeverity(MessageSeverity.Error, true); //infoQueue.SetBreakOnSeverity(MessageSeverity.Warning, true); infoQueue.Dispose(); } debugDevice.Dispose(); } } // Prepare pools CommandAllocators = new CommandAllocatorPool(this); SrvHeaps = new HeapPool(this, SrvHeapSize, DescriptorHeapType.ConstantBufferViewShaderResourceViewUnorderedAccessView); SamplerHeaps = new HeapPool(this, SamplerHeapSize, DescriptorHeapType.Sampler); // Prepare descriptor allocators SamplerAllocator = new DescriptorAllocator(this, DescriptorHeapType.Sampler); ShaderResourceViewAllocator = new DescriptorAllocator(this, DescriptorHeapType.ConstantBufferViewShaderResourceViewUnorderedAccessView); DepthStencilViewAllocator = new DescriptorAllocator(this, DescriptorHeapType.DepthStencilView); RenderTargetViewAllocator = new DescriptorAllocator(this, DescriptorHeapType.RenderTargetView); // Prepare copy command list (start it closed, so that every new use start with a Reset) NativeCopyCommandAllocator = NativeDevice.CreateCommandAllocator(CommandListType.Direct); NativeCopyCommandList = NativeDevice.CreateCommandList(CommandListType.Direct, NativeCopyCommandAllocator, null); NativeCopyCommandList.Close(); // Fence for next frame and resource cleaning nativeFence = NativeDevice.CreateFence(0, FenceFlags.None); nativeCopyFence = NativeDevice.CreateFence(0, FenceFlags.None); }
/// <summary> /// Initializes the specified device. /// </summary> /// <param name="graphicsProfiles">The graphics profiles.</param> /// <param name="deviceCreationFlags">The device creation flags.</param> /// <param name="windowHandle">The window handle.</param> private unsafe void InitializePlatformDevice(GraphicsProfile[] graphicsProfiles, DeviceCreationFlags deviceCreationFlags, object windowHandle) { if (nativeDevice != Device.Null) { // Destroy previous device ReleaseDevice(); } rendererName = Adapter.Description; SharpVulkan.ResultExtensions.SuppressValidationExceptions = (deviceCreationFlags & DeviceCreationFlags.NoValidationExceptions) != 0; PhysicalDeviceProperties physicalDeviceProperties; NativePhysicalDevice.GetProperties(out physicalDeviceProperties); ConstantBufferDataPlacementAlignment = (int)physicalDeviceProperties.Limits.MinUniformBufferOffsetAlignment; TimestampFrequency = (long)(1.0e9 / physicalDeviceProperties.Limits.TimestampPeriod); // Resolution in nanoseconds RequestedProfile = graphicsProfiles.Last(); var queueProperties = NativePhysicalDevice.QueueFamilyProperties; //IsProfilingSupported = queueProperties[0].TimestampValidBits > 0; // Command lists are thread-safe and execute deferred IsDeferred = true; // TODO VULKAN // Create Vulkan device based on profile uint queuePriorities = 0; var queueCreateInfo = new DeviceQueueCreateInfo { StructureType = StructureType.DeviceQueueCreateInfo, QueueFamilyIndex = 0, QueueCount = 1, QueuePriorities = new IntPtr(&queuePriorities) }; NativePhysicalDevice.GetFeatures(out PhysicalDeviceFeatures features); var enabledFeature = new PhysicalDeviceFeatures { FillModeNonSolid = features.FillModeNonSolid, ShaderClipDistance = features.ShaderClipDistance, ShaderCullDistance = features.ShaderCullDistance, SamplerAnisotropy = features.SamplerAnisotropy, DepthClamp = features.DepthClamp, }; var extensionProperties = NativePhysicalDevice.GetDeviceExtensionProperties(); var availableExtensionNames = new List <string>(); var desiredExtensionNames = new List <string>(); for (int index = 0; index < extensionProperties.Length; index++) { var namePointer = new IntPtr(Interop.Fixed(ref extensionProperties[index].ExtensionName)); var name = Marshal.PtrToStringAnsi(namePointer); availableExtensionNames.Add(name); } desiredExtensionNames.Add("VK_KHR_swapchain"); if (!availableExtensionNames.Contains("VK_KHR_swapchain")) { throw new InvalidOperationException(); } if (availableExtensionNames.Contains("VK_EXT_debug_marker") && IsDebugMode) { desiredExtensionNames.Add("VK_EXT_debug_marker"); IsProfilingSupported = true; } var enabledExtensionNames = desiredExtensionNames.Select(Marshal.StringToHGlobalAnsi).ToArray(); try { var deviceCreateInfo = new DeviceCreateInfo { StructureType = StructureType.DeviceCreateInfo, QueueCreateInfoCount = 1, QueueCreateInfos = new IntPtr(&queueCreateInfo), EnabledExtensionCount = (uint)enabledExtensionNames.Length, EnabledExtensionNames = enabledExtensionNames.Length > 0 ? new IntPtr(Interop.Fixed(enabledExtensionNames)) : IntPtr.Zero, EnabledFeatures = new IntPtr(&enabledFeature) }; nativeDevice = NativePhysicalDevice.CreateDevice(ref deviceCreateInfo); } finally { foreach (var enabledExtensionName in enabledExtensionNames) { Marshal.FreeHGlobal(enabledExtensionName); } } NativeCommandQueue = nativeDevice.GetQueue(0, 0); //// Prepare copy command list (start it closed, so that every new use start with a Reset) var commandPoolCreateInfo = new CommandPoolCreateInfo { StructureType = StructureType.CommandPoolCreateInfo, QueueFamilyIndex = 0, //device.NativeCommandQueue.FamilyIndex Flags = CommandPoolCreateFlags.ResetCommandBuffer }; NativeCopyCommandPool = NativeDevice.CreateCommandPool(ref commandPoolCreateInfo); var commandBufferAllocationInfo = new CommandBufferAllocateInfo { StructureType = StructureType.CommandBufferAllocateInfo, Level = CommandBufferLevel.Primary, CommandPool = NativeCopyCommandPool, CommandBufferCount = 1 }; CommandBuffer nativeCommandBuffer; NativeDevice.AllocateCommandBuffers(ref commandBufferAllocationInfo, &nativeCommandBuffer); NativeCopyCommandBuffer = nativeCommandBuffer; DescriptorPools = new HeapPool(this); nativeResourceCollector = new NativeResourceCollector(this); graphicsResourceLinkCollector = new GraphicsResourceLinkCollector(this); EmptyTexelBuffer = Buffer.Typed.New(this, 1, PixelFormat.R32G32B32A32_Float); EmptyTexture = Texture.New2D(this, 1, 1, PixelFormat.R8G8B8A8_UNorm_SRgb, TextureFlags.ShaderResource); }
/// <summary> /// Initializes the specified device. /// </summary> /// <param name="graphicsProfiles">The graphics profiles.</param> /// <param name="deviceCreationFlags">The device creation flags.</param> /// <param name="windowHandle">The window handle.</param> private unsafe void InitializePlatformDevice(GraphicsProfile[] graphicsProfiles, DeviceCreationFlags deviceCreationFlags, object windowHandle) { if (nativeDevice != VkDevice.Null) { // Destroy previous device ReleaseDevice(); } rendererName = Adapter.Description; vkGetPhysicalDeviceProperties(NativePhysicalDevice, out var physicalDeviceProperties); ConstantBufferDataPlacementAlignment = (int)physicalDeviceProperties.limits.minUniformBufferOffsetAlignment; TimestampFrequency = (long)(1.0e9 / physicalDeviceProperties.limits.timestampPeriod); // Resolution in nanoseconds RequestedProfile = graphicsProfiles.Last(); var queueProperties = vkGetPhysicalDeviceQueueFamilyProperties(NativePhysicalDevice); //IsProfilingSupported = queueProperties[0].TimestampValidBits > 0; // Command lists are thread-safe and execute deferred IsDeferred = true; // TODO VULKAN // Create Vulkan device based on profile float queuePriorities = 0; var queueCreateInfo = new VkDeviceQueueCreateInfo { sType = VkStructureType.DeviceQueueCreateInfo, queueFamilyIndex = 0, queueCount = 1, pQueuePriorities = &queuePriorities, }; vkGetPhysicalDeviceFeatures(NativePhysicalDevice, out VkPhysicalDeviceFeatures features); var enabledFeature = new VkPhysicalDeviceFeatures { fillModeNonSolid = features.fillModeNonSolid, shaderClipDistance = features.shaderClipDistance, shaderCullDistance = features.shaderCullDistance, samplerAnisotropy = features.samplerAnisotropy, depthClamp = features.depthClamp, }; var extensionProperties = vkEnumerateDeviceExtensionProperties(NativePhysicalDevice); var availableExtensionNames = new List <string>(); var desiredExtensionNames = new List <string>(); for (int index = 0; index < extensionProperties.Length; index++) { fixed(VkExtensionProperties *extensionPropertiesPtr = extensionProperties) { var namePointer = new IntPtr(extensionPropertiesPtr[index].extensionName); var name = Marshal.PtrToStringAnsi(namePointer); availableExtensionNames.Add(name); } } desiredExtensionNames.Add("VK_KHR_swapchain"); desiredExtensionNames.Add("VK_KHR_external_memory"); desiredExtensionNames.Add("VK_KHR_external_semaphore"); desiredExtensionNames.Add("VK_KHR_dedicated_allocation"); desiredExtensionNames.Add("VK_KHR_get_memory_requirements2"); desiredExtensionNames.Add("VK_KHR_external_memory_win32"); desiredExtensionNames.Add("VK_KHR_win32_keyed_mutex"); if (!availableExtensionNames.Contains("VK_KHR_swapchain")) { throw new InvalidOperationException(); } if (availableExtensionNames.Contains("VK_EXT_debug_marker") && IsDebugMode) { desiredExtensionNames.Add("VK_EXT_debug_marker"); IsProfilingSupported = true; } // take out any extensions not supported for (int i = 0; i < desiredExtensionNames.Count; i++) { if (availableExtensionNames.Contains(desiredExtensionNames[i]) == false) { desiredExtensionNames.RemoveAt(i); i--; } } var enabledExtensionNames = desiredExtensionNames.Select(Marshal.StringToHGlobalAnsi).ToArray(); try { var deviceCreateInfo = new VkDeviceCreateInfo { sType = VkStructureType.DeviceCreateInfo, queueCreateInfoCount = 1, pQueueCreateInfos = &queueCreateInfo, enabledExtensionCount = (uint)enabledExtensionNames.Length, ppEnabledExtensionNames = enabledExtensionNames.Length > 0 ? (byte **)Core.Interop.Fixed(enabledExtensionNames) : null, pEnabledFeatures = &enabledFeature, }; vkCreateDevice(NativePhysicalDevice, &deviceCreateInfo, null, out nativeDevice); } finally { foreach (var enabledExtensionName in enabledExtensionNames) { Marshal.FreeHGlobal(enabledExtensionName); } } vkGetDeviceQueue(nativeDevice, 0, 0, out NativeCommandQueue); //// Prepare copy command list (start it closed, so that every new use start with a Reset) var commandPoolCreateInfo = new VkCommandPoolCreateInfo { sType = VkStructureType.CommandPoolCreateInfo, queueFamilyIndex = 0, //device.NativeCommandQueue.FamilyIndex flags = VkCommandPoolCreateFlags.ResetCommandBuffer }; vkCreateCommandPool(NativeDevice, &commandPoolCreateInfo, null, out NativeCopyCommandPool); var commandBufferAllocationInfo = new VkCommandBufferAllocateInfo { sType = VkStructureType.CommandBufferAllocateInfo, level = VkCommandBufferLevel.Primary, commandPool = NativeCopyCommandPool, commandBufferCount = 1 }; VkCommandBuffer nativeCommandBuffer; vkAllocateCommandBuffers(NativeDevice, &commandBufferAllocationInfo, &nativeCommandBuffer); NativeCopyCommandBuffer = nativeCommandBuffer; DescriptorPools = new HeapPool(this); nativeResourceCollector = new NativeResourceCollector(this); graphicsResourceLinkCollector = new GraphicsResourceLinkCollector(this); EmptyTexelBuffer = Buffer.Typed.New(this, 1, PixelFormat.R32G32B32A32_Float); EmptyTexture = Texture.New2D(this, 1, 1, PixelFormat.R8G8B8A8_UNorm_SRgb, TextureFlags.ShaderResource); // prepare upload buffer now // Allocate buffer that will be recycled nativeUploadBufferSize = Buffer.UploadBufferSizeInMB * 1024 * 1024; var bufferCreateInfo = new VkBufferCreateInfo { sType = VkStructureType.BufferCreateInfo, size = (ulong)nativeUploadBufferSize, flags = VkBufferCreateFlags.None, usage = VkBufferUsageFlags.TransferSrc, }; vkCreateBuffer(NativeDevice, &bufferCreateInfo, null, out nativeUploadBuffer); AllocateMemory(VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent); fixed(IntPtr *nativeUploadBufferStartPtr = &nativeUploadBufferStart) vkMapMemory(NativeDevice, nativeUploadBufferMemory, 0, (ulong)nativeUploadBufferSize, VkMemoryMapFlags.None, (void **)nativeUploadBufferStartPtr); nativeUploadBufferOffset = 0; }