예제 #1
0
        /// <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);
        }
예제 #2
0
        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);
        }