/// <summary>Initializes a new instance of the <see cref="PulseAudioPlaybackDevice" /> class.</summary> internal unsafe PulseAudioPlaybackDevice(IAudioAdapter adapter, pa_context *context) { Assert(context != null, "pa_context passed was null"); if (adapter.DeviceType != AudioDeviceType.Playback) { ThrowInvalidOperationException(nameof(adapter), adapter.DeviceType); } _context = context; _sampleDataPipe = new Pipe(); _stream = new Lazy <IntPtr>(CreateStream, isThreadSafe: true); _writeDelegateHandle = new Lazy <GCHandle>(CreateHandle, isThreadSafe: true); _writeDelegate = new NativeDelegate <pa_stream_request_cb_t>(WriteCallback); _writeRequest = new ManualResetValueTaskSource <int>() { RunContinuationsAsynchronously = true }; Adapter = adapter; _ = _state.Transition(to: Initialized); }
private IntPtr CreateInstance() { var enabledExtensionCount = 0u; var isSurfaceExtensionSupported = false; var isWin32SurfaceExtensionSupported = false; var isXlibSurfaceExtensionSupported = false; var isDebugReportExtensionSupported = false; var extensionPropertyCount = 0u; ThrowExternalExceptionIfFailed(nameof(vkEnumerateInstanceExtensionProperties), vkEnumerateInstanceExtensionProperties(pLayerName: null, &extensionPropertyCount, pProperties: null)); var extensionProperties = new VkExtensionProperties[extensionPropertyCount]; fixed(VkExtensionProperties *pExtensionProperties = extensionProperties) { ThrowExternalExceptionIfFailed(nameof(vkEnumerateInstanceExtensionProperties), vkEnumerateInstanceExtensionProperties(pLayerName: null, &extensionPropertyCount, pExtensionProperties)); } for (var i = 0; i < extensionProperties.Length; i++) { var extensionName = new ReadOnlySpan <sbyte>(Unsafe.AsPointer(ref extensionProperties[i].extensionName[0]), int.MaxValue); extensionName = extensionName.Slice(0, extensionName.IndexOf((sbyte)'\0') + 1); if (!isSurfaceExtensionSupported && VK_KHR_SURFACE_EXTENSION_NAME.SequenceEqual(extensionName)) { isSurfaceExtensionSupported = true; enabledExtensionCount++; } if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (!isWin32SurfaceExtensionSupported && VK_KHR_WIN32_SURFACE_EXTENSION_NAME.SequenceEqual(extensionName)) { isWin32SurfaceExtensionSupported = true; enabledExtensionCount++; } } else { if (!isXlibSurfaceExtensionSupported && VK_KHR_XLIB_SURFACE_EXTENSION_NAME.SequenceEqual(extensionName)) { isXlibSurfaceExtensionSupported = true; enabledExtensionCount++; } } #if DEBUG if (!isDebugReportExtensionSupported && VK_EXT_DEBUG_REPORT_EXTENSION_NAME.SequenceEqual(extensionName)) { isDebugReportExtensionSupported = true; enabledExtensionCount++; } #endif } var enabledExtensionNames = stackalloc sbyte *[(int)enabledExtensionCount]; if (!isSurfaceExtensionSupported) { ThrowInvalidOperationException(nameof(isSurfaceExtensionSupported), isSurfaceExtensionSupported); } enabledExtensionNames[0] = (sbyte *)Unsafe.AsPointer(ref MemoryMarshal.GetReference(VK_KHR_SURFACE_EXTENSION_NAME)); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (!isWin32SurfaceExtensionSupported) { ThrowInvalidOperationException(nameof(isWin32SurfaceExtensionSupported), isWin32SurfaceExtensionSupported); } enabledExtensionNames[1] = (sbyte *)Unsafe.AsPointer(ref MemoryMarshal.GetReference(VK_KHR_WIN32_SURFACE_EXTENSION_NAME)); } else { if (!isXlibSurfaceExtensionSupported) { ThrowInvalidOperationException(nameof(isXlibSurfaceExtensionSupported), isXlibSurfaceExtensionSupported); } enabledExtensionNames[1] = (sbyte *)Unsafe.AsPointer(ref MemoryMarshal.GetReference(VK_KHR_XLIB_SURFACE_EXTENSION_NAME)); } if (isDebugReportExtensionSupported) { // We don't want to throw if the debug extension isn't available enabledExtensionNames[2] = (sbyte *)Unsafe.AsPointer(ref MemoryMarshal.GetReference(VK_EXT_DEBUG_REPORT_EXTENSION_NAME)); } var enabledLayerCount = 0u; var isLunarGStandardValidationLayerSupported = false; #if DEBUG var layerPropertyCount = 0u; ThrowExternalExceptionIfFailed(nameof(vkEnumerateInstanceLayerProperties), vkEnumerateInstanceLayerProperties(&layerPropertyCount, pProperties: null)); var layerProperties = new VkLayerProperties[layerPropertyCount]; fixed(VkLayerProperties *pLayerProperties = layerProperties) { ThrowExternalExceptionIfFailed(nameof(vkEnumerateInstanceLayerProperties), vkEnumerateInstanceLayerProperties(&layerPropertyCount, pLayerProperties)); } for (var i = 0; i < layerProperties.Length; i++) { var layerName = new ReadOnlySpan <sbyte>(Unsafe.AsPointer(ref layerProperties[i].layerName[0]), int.MaxValue); layerName = layerName.Slice(0, layerName.IndexOf((sbyte)'\0') + 1); if (!isLunarGStandardValidationLayerSupported && VK_LAYER_LUNARG_STANDARD_VALIDATION_LAYER_NAME.SequenceEqual(layerName)) { isLunarGStandardValidationLayerSupported = true; enabledLayerCount++; } } #endif var enabledLayerNames = stackalloc sbyte *[(int)enabledLayerCount]; if (isLunarGStandardValidationLayerSupported) { enabledLayerNames[0] = (sbyte *)Unsafe.AsPointer(ref MemoryMarshal.GetReference(VK_LAYER_LUNARG_STANDARD_VALIDATION_LAYER_NAME)); } var applicationInfo = new VkApplicationInfo { sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, pNext = null, pApplicationName = null, applicationVersion = 1, pEngineName = (sbyte *)Unsafe.AsPointer(ref MemoryMarshal.GetReference(s_engineName)), engineVersion = VK_MAKE_VERSION(0, 1, 0), apiVersion = VK_API_VERSION_1_0, }; var createInfo = new VkInstanceCreateInfo { sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, pNext = null, flags = 0, pApplicationInfo = &applicationInfo, enabledLayerCount = enabledLayerCount, ppEnabledLayerNames = enabledLayerNames, enabledExtensionCount = enabledExtensionCount, ppEnabledExtensionNames = enabledExtensionNames, }; IntPtr instance; var result = vkCreateInstance(&createInfo, null, &instance); if (result != VK_SUCCESS) { ThrowExternalException(nameof(vkCreateInstance), (int)result); } if (isDebugReportExtensionSupported && isLunarGStandardValidationLayerSupported) { #if DEBUG ulong debugReportCallbackExt; _debugReportCallback = new NativeDelegate <PFN_vkDebugReportCallbackEXT>(DebugReportCallback); var debugReportCallbackCreateInfo = new VkDebugReportCallbackCreateInfoEXT { sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, pNext = null, flags = (uint)(VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT), pfnCallback = _debugReportCallback, pUserData = null, }; // We don't want to fail if creating the debug report callback failed var vkCreateDebugReportCallbackEXT = vkGetInstanceProcAddr(instance, (sbyte *)Unsafe.AsPointer(ref MemoryMarshal.GetReference(VKCREATEDEBUGREPORTCALLBACKEXT_FUNCTION_NAME))); _ = Marshal.GetDelegateForFunctionPointer <PFN_vkCreateDebugReportCallbackEXT>(vkCreateDebugReportCallbackEXT)(instance, &debugReportCallbackCreateInfo, pAllocator : null, &debugReportCallbackExt); _debugReportCallbackExt = debugReportCallbackExt; #endif } return(instance); }