Mesa3D не нравится мой код создания контекста?
Сегодня я снял свою зависимость от OpenTK; мое приложение больше не использует OpenTK для создания контекста OpenGL. Однако мой код больше не работает приемлемо при запуске в Mesa 3D (программная реализация OpenGL); мой код выполняется, но FPS составляет около 0,001 FPS (по сравнению с 16+FPS, использующими создание контекста OpenTK), и материал, который обычно рисуется в FBO, отображается в окне, фрагмент за фрагментом, как он составлен. Хотя мой код без Mesa 3D приводит к нормальной производительности (в Windows 7), я боюсь, что это может совпадать с тем, что он работает хорошо. glGetError
Проверка не показывает ошибок, что заставляет меня думать, что, возможно, я что-то не так делаю в создании контекста?
m_controlHandle = m_winForm.Handle; /* HWND */
m_controlDC = Win32.GetDC(m_controlHandle); /* HWND's DC*/
Win32.PixelFormatDescriptor pixelFormat = new Win32.PixelFormatDescriptor();
pixelFormat.Size = (short)Marshal.SizeOf(typeof(Win32.PixelFormatDescriptor));
pixelFormat.Version = 1;
pixelFormat.Flags =
Win32.PixelFormatDescriptorFlags.DRAW_TO_WINDOW |
Win32.PixelFormatDescriptorFlags.SUPPORT_OPENGL |
Win32.PixelFormatDescriptorFlags.DOUBLEBUFFER;
pixelFormat.PixelType = Win32.PixelType.RGBA;
pixelFormat.ColorBits = 32;
pixelFormat.DepthBits = 0; /* yes, I don't use a depth buffer; 2D sprite game */
pixelFormat.LayerType = Win32.PixelFormatLayerType.MAIN_PLANE;
int formatCode = Win32.ChoosePixelFormat(m_controlDC, ref pixelFormat);
if (formatCode == 0)
throw new Win32Exception(Marshal.GetLastWin32Error());
if (!Win32.SetPixelFormat(m_controlDC, formatCode, ref pixelFormat))
throw new Win32Exception(Marshal.GetLastWin32Error());
m_openGLContext = Win32.wglCreateContext(m_controlDC);
if (m_openGLContext == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error());
if (!Win32.wglMakeCurrent(m_controlDC, m_openGLContext))
throw new Exception("Could not wglMakeCurrent.");
Это правильно? Любые предложения по отслеживанию того, что может привести к тому, что Mesa3D вдруг сойдет с ума?
2 ответа
Хорошо... Я надеюсь, что никто не должен проходить через то, что я сделал, пытаясь понять это, так что вот решение:
Хотя OpenTK попытается использовать wglChoosePixelFormatARB
, он не работает на Mesa 3D и возвращается к ChoosePixelFormat
, Тем не менее, функция, которую вызывает OpenTK ChoosePixelFormat
на самом деле DllImports
wglChoosePixelFormat
и не ChoosePixelFormat
,
Да, есть две версии ChoosePixelFormat
: один с префиксом wgl
и один без префикса. Из документации OpenGL.org:
На платформе Win32 несколько вызовов функций, специфичных для данной платформы, дублируются в механизме OpenGL ICD и GDI. Это может вызвать путаницу, так как они кажутся функционально идентичными, единственное отличие состоит в том, предшествует ли wgl остальной части имени функции. Чтобы обеспечить правильную работу OpenGL, используйте ChoosePixelformat, DescribePixelformat, GetPixelformat, SetPixelformat и SwapBuffers вместо wgl-эквивалентов, wglChoosePixelformat, wglDescribePixelformat, wglGetPixelformat и wg. Forfors, wg. Во всех остальных случаях используйте функцию wgl, если она доступна. Использование пяти функций wgl представляет интерес только для разработчиков, устанавливающих связь с драйвером OpenGL. Неиспользование описанных функций может привести к черному окну OpenGL или к правильно работающему приложению в Windows 9x, которое создает черное окно OpenGL в Windows NT/2000.
Как я пытаюсь во время выполнения ссылку на драйвер OpenGL (Mesa 3D), пять wgl
функции представляют интерес для меня. Однажды я заменил мой ChoosePixelFormat
, SetPixelformat
, а также SwapBuffers
с wglChoosePixelFormat
, wglSetPixelformat
, а также wglSwapBuffers
Mesa 3D работал отлично! Тайна разгадана.
У вас есть большой недостаток в вашей логике при выборе формата пикселей, если вы хотите избежать программной реализации. Вспомните (или узнайте впервые), что WGL использует эвристику сопоставления с образцом, которая ищет набор всех форматов пикселей, которые минимально удовлетворяют запрошенным параметрам. Чем больше запрошенных параметров вы оставите равными 0, тем больше неопределенности уйдет, когда придет время разрешить "лучшее" (самое близкое) соответствие.
Если вы хотите понять, почему 0-битный буфер глубины в сочетании с 32-битным цветным буфером может быть плохой идеей, вы можете перечислить все форматы пикселей, предлагаемые вашим драйвером дисплея, и проверить, какие из них полностью аппаратно ускорены (они не будет флага: PFD_GENERIC_FORMAT
или же PFD_GENERIC_ACCELERATED
задавать). Есть программное обеспечение, которое сделает это для вас, хотя я не могу думать ни о чем из головы - будьте готовы просмотреть список сотен форматов пикселей, если вы действительно решите сделать это...
Многие странные комбинации параметров реализованы в программном обеспечении (GDI), но не в аппаратном обеспечении. Одной из лучших битовых глубин, чтобы попробовать получить аппаратный формат, является 32-битный RGBA, 24-битная глубина, 8-битный трафарет. На современном оборудовании это почти всегда то, что драйвер выберет в качестве "наиболее близкого" соответствия для наиболее разумных комбинаций входных параметров. Чем ближе вы подходите к выбору точного аппаратного пиксельного формата, тем больше вероятность того, что Win32 / WGL не предоставит вам пиксельный формат GDI.
Основываясь на моих собственных наблюдениях:
Я должен был вручную перечислить форматы пикселей и переопределить поведение ChoosePixelFormat (...)
обойти ошибки водителя в далеком прошлом; поведение сопоставления с образцом не всегда работает в вашу пользу.
В случае OpenTK, я подозреваю, что он на самом деле использует wglChoosePixelFormatARB (...)
Это совершенно более сложный интерфейс для выбора форматов пикселей (и необходимый для поддержки мультисэмплирования сглаживания). wglChoosePixelFormatARB
реализован с помощью устанавливаемого драйвера клиента (ICD), поэтому он никогда не пытается сопоставить входные параметры с форматами пикселей GDI.
Я подозреваю, что GDI предоставляет 32-битный формат RGBA + 0-битный Z-пиксель, но ваш ICD - нет. Поскольку ближайший матч всегда выигрывает, и ChoosePixelFormat
видит GDI пиксельные форматы, вы можете понять, почему это проблема.
Вам следует попробовать 32-битный RGBA (24-битный цвет, 8-битный альфа) + 24-битный Z + 8-битный трафарет и посмотреть, улучшит ли это вашу производительность...
Обновить:
Есть еще одна проблема, которая может привести к отключению некоторых драйверов глупее. ColorBits
предполагается, что это число бит RGB в пиксельном формате RGBA (обычно 24). AlphaBits
Предполагается, что это число битов A (обычно 8). Многие драйверы увидят 32-битные ColorBits
в сочетании с 0 AlphaBits
и понять подразумеваемое поведение (24-битный RGB + 8-битный отступ), но способ написания кода может быть проблематичным. Технически этот вид пиксельного формата будет называться RGBX8
(где Х обозначает неиспользованные биты).
24 ColorBits
и 8 AlphaBits
может дать более переносимые результаты.